From 5a094a30338639648a89b365419263761064ca86 Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 16:22:42 +0200 Subject: [PATCH 01/29] Snap Trap --- include/constants/battle_string_ids.h | 3 ++- src/battle_message.c | 5 ++++- src/battle_script_commands.c | 2 +- src/data/battle_moves.h | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index cda885694..cf26ef2ef 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -570,8 +570,9 @@ #define STRINGID_MICLEBERRYACTIVATES 566 #define STRINGID_PKMNSHOOKOFFTHETAUNT 567 #define STRINGID_PKMNGOTOVERITSINFATUATION 568 +#define STRINGID_PKMNINSNAPTRAP 569 -#define BATTLESTRINGS_COUNT 569 +#define BATTLESTRINGS_COUNT 570 // 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 c4f043e15..d8b0fc8f9 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -147,6 +147,7 @@ static const u8 sText_PkmnDugHole[] = _("{B_ATK_NAME_WITH_PREFIX} dug a hole!"); static const u8 sText_PkmnHidUnderwater[] = _("{B_ATK_NAME_WITH_PREFIX} hid\nunderwater!"); static const u8 sText_PkmnSprangUp[] = _("{B_ATK_NAME_WITH_PREFIX} sprang up!"); static const u8 sText_PkmnSqueezedByBind[] = _("{B_DEF_NAME_WITH_PREFIX} was squeezed by\n{B_ATK_NAME_WITH_PREFIX}'s BIND!"); +static const u8 sText_PkmnInSnapTrap[] = _("{B_DEF_NAME_WITH_PREFIX} got trapped\nby a snap trap!"); static const u8 sText_PkmnTrappedInVortex[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nin the vortex!"); static const u8 sText_PkmnTrappedBySandTomb[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nby SAND TOMB!"); static const u8 sText_PkmnWrappedBy[] = _("{B_DEF_NAME_WITH_PREFIX} was WRAPPED by\n{B_ATK_NAME_WITH_PREFIX}!"); @@ -699,6 +700,7 @@ static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_P const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_PKMNINSNAPTRAP - 12] = sText_PkmnInSnapTrap, [STRINGID_PKMNGOTOVERITSINFATUATION - 12] = sText_PkmnGotOverItsInfatuation, [STRINGID_PKMNSHOOKOFFTHETAUNT - 12] = sText_PkmnShookOffTheTaunt, [STRINGID_MICLEBERRYACTIVATES - 12] = sText_MicleBerryActivates, @@ -1463,6 +1465,7 @@ const u16 gWrappedStringIds[] = STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL STRINGID_PKMNTRAPPEDBYSANDTOMB,// MOVE_SAND_TOMB STRINGID_INFESTATION, // MOVE_INFESTATION + STRINGID_PKMNINSNAPTRAP, // MOVE_SNAPTRAP }; const u16 gMistUsedStringIds[] = @@ -1675,7 +1678,7 @@ const u16 gCaughtMonStringIds[] = const u16 gTrappingMoves[] = { - MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_INFESTATION, 0xFFFF + MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_INFESTATION, MOVE_SNAP_TRAP, 0xFFFF }; const u16 gRoomsStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c8a393da3..014c3c3c8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2895,7 +2895,7 @@ void SetMoveEffect(bool32 primary, u32 certain) for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; ; gBattleCommunication[MULTISTRING_CHOOSER]++) { - if (gBattleCommunication[MULTISTRING_CHOOSER] > 5) + if (gBattleCommunication[MULTISTRING_CHOOSER] > 6) break; if (gTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) break; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index db02083b0..69b612e0c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10968,7 +10968,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SNAP_TRAP] = { - .effect = EFFECT_TRAP, //TODO: add case/effect + .effect = EFFECT_TRAP, .power = 35, .type = TYPE_GRASS, .accuracy = 100, From 60ce39543e8c918110c23deec7826e237851e2a6 Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 16:25:59 +0200 Subject: [PATCH 02/29] Expanding Force --- data/battle_scripts_1.s | 2 ++ include/constants/battle_move_effects.h | 3 ++- src/battle_util.c | 4 ++++ src/data/battle_moves.h | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 11616e300..6e667ebfe 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -369,6 +369,7 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectSleepHit .4byte BattleScript_EffectAttackerDefenseDownHit .4byte BattleScript_EffectBodyPress + .4byte BattleScript_EffectExpandingForce BattleScript_EffectAttackerDefenseDownHit: setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN @@ -2059,6 +2060,7 @@ BattleScript_EffectFusionCombo: BattleScript_EffectRevelationDance: BattleScript_EffectBelch: BattleScript_EffectBodyPress: +BattleScript_EffectExpandingForce: BattleScript_HitFromAtkCanceler:: attackcanceler diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 6174ca496..cfd4ccdef 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -353,7 +353,8 @@ #define EFFECT_SLEEP_HIT 347 // Relic Song #define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 348 #define EFFECT_BODY_PRESS 349 +#define EFFECT_EXPANDING_FORCE 350 -#define NUM_BATTLE_MOVE_EFFECTS 350 +#define NUM_BATTLE_MOVE_EFFECTS 351 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_util.c b/src/battle_util.c index 0c8f2c8d1..92662bb20 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7210,6 +7210,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (gBattleMoves[gLastUsedMove].effect == EFFECT_FUSION_COMBO && move != gLastUsedMove) basePower *= 2; break; + case EFFECT_EXPANDING_FORCE: + if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + basePower = 120; + break; } if (basePower == 0) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 69b612e0c..b556a0a5c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11220,7 +11220,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_EXPANDING_FORCE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_EXPANDING_FORCE, .power = 80, .type = TYPE_PSYCHIC, .accuracy = 100, From 62525516a4e59d32693383b9835ce07e4b4fcf27 Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 16:50:19 +0200 Subject: [PATCH 03/29] Scale Shot --- data/battle_scripts_1.s | 57 +++++++++++++++++++++++++ include/constants/battle.h | 3 +- include/constants/battle_move_effects.h | 3 +- src/data/battle_moves.h | 4 +- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6e667ebfe..d85b8cff8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -370,6 +370,63 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectAttackerDefenseDownHit .4byte BattleScript_EffectBodyPress .4byte BattleScript_EffectExpandingForce + .4byte BattleScript_EffectScaleShot + +BattleScript_EffectScaleShot:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + setmultihitcounter 0x0 + initmultihitstring + sethword sMULTIHIT_EFFECT, 0x0 +BattleScript_ScaleShotLoop:: + jumpifhasnohp BS_ATTACKER, BattleScript_ScaleShotEnd + jumpifhasnohp BS_TARGET, BattleScript_ScaleShotPrintStrings + jumpifhalfword CMP_EQUAL, gChosenMove, MOVE_SLEEP_TALK, BattleScript_ScaleShotDoMultiHit + jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_ScaleShotPrintStrings +BattleScript_ScaleShotDoMultiHit:: + movevaluescleanup + copyhword sMOVE_EFFECT, sMULTIHIT_EFFECT + critcalc + damagecalc + jumpifmovehadnoeffect BattleScript_ScaleShotMultiHitNoMoreHits + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + multihitresultmessage + printstring STRINGID_EMPTYSTRING3 + waitmessage 0x1 + addbyte sMULTIHIT_STRING + 4, 0x1 + moveendto MOVEEND_NEXT_TARGET + jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_FOE_ENDURED, BattleScript_ScaleShotPrintStrings + decrementmultihit BattleScript_ScaleShotLoop + goto BattleScript_ScaleShotPrintStrings +BattleScript_ScaleShotMultiHitNoMoreHits:: + pause 0x20 +BattleScript_ScaleShotPrintStrings:: + resultmessage + waitmessage 0x40 + jumpifmovehadnoeffect BattleScript_ScaleShotEnd + copyarray gBattleTextBuff1, sMULTIHIT_STRING, 0x6 + printstring STRINGID_HITXTIMES + waitmessage 0x40 +BattleScript_ScaleShotEnd:: + setmoveeffect MOVE_EFFECT_SPD_PLUS_1 | MOVE_EFFECT_AFFECTS_USER + seteffectwithchance + setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER + seteffectwithchance + tryfaintmon BS_TARGET, FALSE, NULL + moveendcase MOVEEND_SYNCHRONIZE_TARGET + moveendfrom MOVEEND_STATUS_IMMUNITY_ABILITIES + end BattleScript_EffectAttackerDefenseDownHit: setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN diff --git a/include/constants/battle.h b/include/constants/battle.h index b158076bd..b925904c2 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -346,7 +346,8 @@ #define MOVE_EFFECT_THROAT_CHOP 0x43 #define MOVE_EFFECT_INCINERATE 0x44 #define MOVE_EFFECT_BUG_BITE 0x45 -#define NUM_MOVE_EFFECTS 0x46 +#define MOVE_EFFECT_SPD_PLUS_1_DEF_MINUS_1 0x46 +#define NUM_MOVE_EFFECTS 0x47 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index cfd4ccdef..fd26204a1 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -354,7 +354,8 @@ #define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 348 #define EFFECT_BODY_PRESS 349 #define EFFECT_EXPANDING_FORCE 350 +#define EFFECT_SCALE_SHOT 351 -#define NUM_BATTLE_MOVE_EFFECTS 351 +#define NUM_BATTLE_MOVE_EFFECTS 352 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index b556a0a5c..83ff193a3 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11248,12 +11248,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SCALE_SHOT] = { - .effect = EFFECT_PLACEHOLDER, //TODO (EFFECT_MULTI_HIT + ABILITY_WEAK_ARMOR, + .effect = EFFECT_SCALE_SHOT, .power = 25, .type = TYPE_DRAGON, .accuracy = 90, .pp = 20, - .secondaryEffectChance = 0, + .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, From ee3f3eb78f5a51b8cb81b282a04fc2771d945bb7 Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 17:06:21 +0200 Subject: [PATCH 04/29] Meteor Beam --- data/battle_scripts_1.s | 27 +++++++++++++++++++++++++ include/constants/battle_move_effects.h | 3 ++- include/constants/battle_string_ids.h | 6 ++++-- src/battle_message.c | 3 +++ src/data/battle_moves.h | 2 +- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d85b8cff8..cc6a37668 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -371,6 +371,33 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectBodyPress .4byte BattleScript_EffectExpandingForce .4byte BattleScript_EffectScaleShot + .4byte BattleScript_EffectMeteorBeam + +BattleScript_EffectMeteorBeam:: + @ DecideTurn + jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn + jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn + setbyte sTWOTURN_STRINGID, B_MSG_TURN1_METEOR_BEAM + call BattleScript_FirstChargingTurnMeteorBeam + jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd + call BattleScript_PowerHerbActivation + goto BattleScript_TwoTurnMovesSecondTurn + +BattleScript_FirstChargingTurnMeteorBeam:: + attackcanceler + printstring STRINGID_EMPTYSTRING3 + ppreduce + attackanimation + waitanimation + orword gHitMarker, HITMARKER_CHARGING + setmoveeffect MOVE_EFFECT_CHARGING | MOVE_EFFECT_AFFECTS_USER + seteffectprimary + copybyte cMULTISTRING_CHOOSER, sTWOTURN_STRINGID + printfromtable gFirstTurnOfTwoStringIds + waitmessage 0x40 + setmoveeffect MOVE_EFFECT_SP_ATK_PLUS_1 | MOVE_EFFECT_AFFECTS_USER + seteffectsecondary + return BattleScript_EffectScaleShot:: attackcanceler diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index fd26204a1..47721e447 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -355,7 +355,8 @@ #define EFFECT_BODY_PRESS 349 #define EFFECT_EXPANDING_FORCE 350 #define EFFECT_SCALE_SHOT 351 +#define EFFECT_METEOR_BEAM 352 -#define NUM_BATTLE_MOVE_EFFECTS 352 +#define NUM_BATTLE_MOVE_EFFECTS 353 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index cf26ef2ef..c1e35a312 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -570,9 +570,10 @@ #define STRINGID_MICLEBERRYACTIVATES 566 #define STRINGID_PKMNSHOOKOFFTHETAUNT 567 #define STRINGID_PKMNGOTOVERITSINFATUATION 568 -#define STRINGID_PKMNINSNAPTRAP 569 +#define STRINGID_PKMNINSNAPTRAP 569 +#define STRINGID_METEORBEAMCHARGING 570 -#define BATTLESTRINGS_COUNT 570 +#define BATTLESTRINGS_COUNT 571 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. @@ -623,6 +624,7 @@ #define B_MSG_TURN1_PHANTOM_FORCE 8 #define B_MSG_TURN1_GEOMANCY 9 #define B_MSG_TURN1_FREEZE_SHOCK 10 +#define B_MSG_TURN1_METEOR_BEAM 11 // gMoveWeatherChangeStringIds #define B_MSG_STARTED_RAIN 0 diff --git a/src/battle_message.c b/src/battle_message.c index d8b0fc8f9..fd33527a2 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -697,9 +697,11 @@ static const u8 sText_CanActFaster[] = _("{B_ATK_NAME_WITH_PREFIX} can act faste static const u8 sText_MicleBerryActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted the accuracy of its\nnext move using {B_LAST_ITEM}!"); static const u8 sText_PkmnShookOffTheTaunt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} shook off\nthe taunt!"); static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} got over\nits infatuation!"); +static const u8 sText_MeteorBeamCharging[] = _("{B_ATK_NAME_WITH_PREFIX} is overflowing\nwith space energy!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_METEORBEAMCHARGING - 12] = sText_MeteorBeamCharging, [STRINGID_PKMNINSNAPTRAP - 12] = sText_PkmnInSnapTrap, [STRINGID_PKMNGOTOVERITSINFATUATION - 12] = sText_PkmnGotOverItsInfatuation, [STRINGID_PKMNSHOOKOFFTHETAUNT - 12] = sText_PkmnShookOffTheTaunt, @@ -1453,6 +1455,7 @@ const u16 gFirstTurnOfTwoStringIds[] = [B_MSG_TURN1_PHANTOM_FORCE] = STRINGID_VANISHEDINSTANTLY, [B_MSG_TURN1_GEOMANCY] = STRINGID_PKNMABSORBINGPOWER, [B_MSG_TURN1_FREEZE_SHOCK] = STRINGID_CLOAKEDINAFREEZINGLIGHT, + [B_MSG_TURN1_METEOR_BEAM] = STRINGID_METEORBEAMCHARGING, }; // Index copied from move's index in gTrappingMoves diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 83ff193a3..680c008fd 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11262,7 +11262,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_METEOR_BEAM] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_METEOR_BEAM, .power = 120, .type = TYPE_ROCK, .accuracy = 90, From e7ec4df70bf89def1630b5e184b431d3e46eaf7a Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 17:36:50 +0200 Subject: [PATCH 05/29] Rising Voltage --- data/battle_scripts_1.s | 2 ++ include/constants/battle_move_effects.h | 3 ++- src/battle_util.c | 5 +++++ src/data/battle_moves.h | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index cc6a37668..2e5ad0253 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -372,6 +372,7 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectExpandingForce .4byte BattleScript_EffectScaleShot .4byte BattleScript_EffectMeteorBeam + .4byte BattleScript_EffectRisingVoltage BattleScript_EffectMeteorBeam:: @ DecideTurn @@ -2145,6 +2146,7 @@ BattleScript_EffectRevelationDance: BattleScript_EffectBelch: BattleScript_EffectBodyPress: BattleScript_EffectExpandingForce: +BattleScript_EffectRisingVoltage: BattleScript_HitFromAtkCanceler:: attackcanceler diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 47721e447..03ea11136 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -356,7 +356,8 @@ #define EFFECT_EXPANDING_FORCE 350 #define EFFECT_SCALE_SHOT 351 #define EFFECT_METEOR_BEAM 352 +#define EFFECT_RISING_VOLTAGE 353 -#define NUM_BATTLE_MOVE_EFFECTS 353 +#define NUM_BATTLE_MOVE_EFFECTS 354 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_util.c b/src/battle_util.c index 92662bb20..4c46250dc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7214,6 +7214,11 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) basePower = 120; break; + case EFFECT_RISING_VOLTAGE: + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING) + && gBattleMons[battlerDef].item != ITEM_AIR_BALLOON && gBattleMons[battlerDef].ability != ABILITY_LEVITATE) + basePower *= 2; + break; } if (basePower == 0) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 680c008fd..9e0c18298 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11318,7 +11318,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_RISING_VOLTAGE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_RISING_VOLTAGE, .power = 70, .type = TYPE_ELECTRIC, .accuracy = 100, From 7799e49e3a3f5ef65a39c7acd392b05b3b61961e Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 19:44:38 +0200 Subject: [PATCH 06/29] Corrosive Gas --- asm/macros/battle_script.inc | 5 +++ data/battle_scripts_1.s | 19 ++++++++++ include/battle.h | 1 + include/battle_scripts.h | 1 + include/constants/battle.h | 1 + include/constants/battle_move_effects.h | 3 +- include/constants/battle_script_commands.h | 1 + include/constants/battle_string_ids.h | 3 +- src/battle_message.c | 2 + src/battle_script_commands.c | 43 ++++++++++++++++++++-- src/battle_util.c | 5 +++ src/data/battle_moves.h | 2 +- 12 files changed, 80 insertions(+), 6 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9fa3fe0c3..9384a0f9d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1769,6 +1769,11 @@ various \battler, VARIOUS_TRY_ACTIVATE_GRIM_NEIGH .endm + .macro trysetcorrosivegas battler:req, ptr:req + various \battler, VARIOUS_TRY_SET_CORROSIVE_GAS + .4byte \ptr + .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 2e5ad0253..e1e7fbf9d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -373,6 +373,25 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectScaleShot .4byte BattleScript_EffectMeteorBeam .4byte BattleScript_EffectRisingVoltage + .4byte BattleScript_EffectCorrosiveGas + +BattleScript_EffectCorrosiveGas:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON + attackstring + ppreduce + jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_PrintMoveMissed + trysetcorrosivegas BS_TARGET, BattleScript_ButItFailed + attackanimation + waitanimation + printstring STRINGID_ITEMMELTED + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_MeltedItem:: + printstring STRINGID_ITEMMELTED + waitmessage 0x40 + return BattleScript_EffectMeteorBeam:: @ DecideTurn diff --git a/include/battle.h b/include/battle.h index f009cbe7f..7212c4084 100644 --- a/include/battle.h +++ b/include/battle.h @@ -229,6 +229,7 @@ struct WishFutureKnock u8 wishMonId[MAX_BATTLERS_COUNT]; u8 weatherDuration; u8 knockedOffMons[2]; // Each battler is represented by a bit. The array entry is dependent on the battler's side. + u8 meltedItemMons[2]; // Same as above }; struct AI_SavedBattleMon diff --git a/include/battle_scripts.h b/include/battle_scripts.h index f0712fc43..7ae55d01f 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -369,5 +369,6 @@ extern const u8 BattleScript_JabocaRowapBerryActivates[]; extern const u8 BattleScript_NotAffectedAbilityPopUp[]; extern const u8 BattleScript_BattlerShookOffTaunt[]; extern const u8 BattleScript_BattlerGotOverItsInfatuation[]; +extern const u8 BattleScript_MeltedItem[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle.h b/include/constants/battle.h index b925904c2..d7bae55c3 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -347,6 +347,7 @@ #define MOVE_EFFECT_INCINERATE 0x44 #define MOVE_EFFECT_BUG_BITE 0x45 #define MOVE_EFFECT_SPD_PLUS_1_DEF_MINUS_1 0x46 +#define MOVE_EFFECT_MELT_ITEM 0x4A #define NUM_MOVE_EFFECTS 0x47 #define MOVE_EFFECT_AFFECTS_USER 0x4000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 03ea11136..d88b34a53 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -357,7 +357,8 @@ #define EFFECT_SCALE_SHOT 351 #define EFFECT_METEOR_BEAM 352 #define EFFECT_RISING_VOLTAGE 353 +#define EFFECT_CORROSIVE_GAS 354 -#define NUM_BATTLE_MOVE_EFFECTS 354 +#define NUM_BATTLE_MOVE_EFFECTS 355 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index faaf8f17e..f35dbe2e3 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -173,6 +173,7 @@ #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 +#define VARIOUS_TRY_SET_CORROSIVE_GAS 105 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index c1e35a312..72f178de7 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -572,8 +572,9 @@ #define STRINGID_PKMNGOTOVERITSINFATUATION 568 #define STRINGID_PKMNINSNAPTRAP 569 #define STRINGID_METEORBEAMCHARGING 570 +#define STRINGID_ITEMMELTED 571 -#define BATTLESTRINGS_COUNT 571 +#define BATTLESTRINGS_COUNT 572 // 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 fd33527a2..4d1ae2ddb 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -698,9 +698,11 @@ static const u8 sText_MicleBerryActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} static const u8 sText_PkmnShookOffTheTaunt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} shook off\nthe taunt!"); static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} got over\nits infatuation!"); 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}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_ITEMMELTED - 12] = sText_PkmnItemMelted, [STRINGID_METEORBEAMCHARGING - 12] = sText_MeteorBeamCharging, [STRINGID_PKMNINSNAPTRAP - 12] = sText_PkmnInSnapTrap, [STRINGID_PKMNGOTOVERITSINFATUATION - 12] = sText_PkmnGotOverItsInfatuation, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 014c3c3c8..9915654c5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3021,7 +3021,8 @@ void SetMoveEffect(bool32 primary, u32 certain) | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_SECRET_BASE)) - && (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]])) + && (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] + || gWishFutureKnock.meltedItemMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]])) { gBattlescriptCurrInstr++; } @@ -5267,6 +5268,11 @@ static void Cmd_switchindataupdate(void) { gBattleMons[gActiveBattler].item = 0; } + // check melted items + if (gWishFutureKnock.meltedItemMons[i] & gBitTable[gBattlerPartyIndexes[gActiveBattler]]) + { + gBattleMons[gActiveBattler].item = 0; + } if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS) { @@ -8422,6 +8428,35 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe) } return; + case VARIOUS_TRY_SET_CORROSIVE_GAS: + if (gBattleMons[gActiveBattler].item != 0 + && CanBattlerGetOrLoseItem(gActiveBattler, gBattleMons[gActiveBattler].item) + && !NoAliveMonsForEitherParty()) + { + if (GetBattlerAbility(gActiveBattler) == ABILITY_STICKY_HOLD && IsBattlerAlive(gActiveBattler)) + { + gBattlerAbility = gActiveBattler; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; + } + else + { //Item is melted normally + u32 side = GetBattlerSide(gActiveBattler); + + gLastUsedItem = gBattleMons[gActiveBattler].item; + gBattleMons[gActiveBattler].item = 0; + gBattleStruct->choicedMove[gActiveBattler] = 0; + gWishFutureKnock.meltedItemMons[side] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]]; + + CheckSetUnburden(gActiveBattler); + gBattlescriptCurrInstr += 7; + } + } + else + { + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + } + return; } gBattlescriptCurrInstr += 3; @@ -11206,14 +11241,16 @@ static void Cmd_tryswapitems(void) // trick u8 sideAttacker = GetBattlerSide(gBattlerAttacker); u8 sideTarget = GetBattlerSide(gBattlerTarget); - // you can't swap items if they were knocked off in regular battles + // you can't swap items if they were knocked off or melted in regular battles if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_RECORDED_LINK)) && (gWishFutureKnock.knockedOffMons[sideAttacker] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] - || gWishFutureKnock.knockedOffMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]])) + || gWishFutureKnock.knockedOffMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]] + || gWishFutureKnock.meltedItemMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] + || gWishFutureKnock.meltedItemMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]])) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } diff --git a/src/battle_util.c b/src/battle_util.c index 4c46250dc..9d7453bab 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7215,8 +7215,13 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower = 120; break; case EFFECT_RISING_VOLTAGE: + #ifdef ITEM_EXPANSION //Air Baloon exception with item expansion branch if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING) && gBattleMons[battlerDef].item != ITEM_AIR_BALLOON && gBattleMons[battlerDef].ability != ABILITY_LEVITATE) + #else + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING) + && gBattleMons[battlerDef].ability != ABILITY_LEVITATE) + #endif basePower *= 2; break; } diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 9e0c18298..20449e446 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11402,7 +11402,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_CORROSIVE_GAS] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_CORROSIVE_GAS, .power = 0, .type = TYPE_POISON, .accuracy = 100, From 0202b75822bbbc98787c28a6d19ce754b15ae5fb Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 19:57:21 +0200 Subject: [PATCH 07/29] Beak Blast --- asm/macros/battle_script.inc | 4 +++ data/battle_anim_scripts.s | 5 ++-- data/battle_scripts_1.s | 30 ++++++++++++++++++++++ include/battle.h | 1 + include/battle_scripts.h | 2 ++ include/constants/battle_anim.h | 1 + include/constants/battle_move_effects.h | 3 ++- include/constants/battle_script_commands.h | 1 + include/constants/battle_string_ids.h | 3 ++- src/battle_main.c | 14 +++++++--- src/battle_message.c | 2 ++ src/battle_script_commands.c | 10 ++++++++ src/data/battle_moves.h | 2 +- 13 files changed, 69 insertions(+), 9 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9384a0f9d..1405dd258 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1774,6 +1774,10 @@ .4byte \ptr .endm + .macro setbeakblast battler:req + various \battler, VARIOUS_SET_BEAK_BLAST + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 65bac00d7..ee401010a 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -822,6 +822,7 @@ gBattleAnims_General:: .4byte General_SlideOffScreen @ B_ANIM_SLIDE_OFFSCREEN .4byte General_RestoreBg @ B_ANIM_RESTORE_BG .4byte General_TotemFlare @ B_ANIM_TOTEM_FLARE + .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP .align 2 gBattleAnims_Special:: @@ -11673,7 +11674,7 @@ Move_INSTRUCT:: blendoff end -Move_BEAK_BLAST:: +General_BeakBlastSetUp: loadspritegfx ANIM_TAG_SMALL_EMBER @Fire playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER delay 0x3 @@ -11681,7 +11682,7 @@ Move_BEAK_BLAST:: launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x0 waitforvisualfinish end -BeakBlastUnleash: +Move_BEAK_BLAST:: loadspritegfx ANIM_TAG_IMPACT launchtask AnimTask_BlendBattleAnimPal 0xA 0x5 ANIM_PAL_ATK 0x2 0x0 0x9 0x1F waitforvisualfinish diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e1e7fbf9d..02da8a3bb 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -374,7 +374,37 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectMeteorBeam .4byte BattleScript_EffectRisingVoltage .4byte BattleScript_EffectCorrosiveGas + .4byte BattleScript_EffectBeakBlast +BattleScript_EffectBeakBlast:: + attackcanceler + jumpifnodamage BattleScript_HitFromAccCheck + ppreduce + printstring STRINGID_PKMNLOSTFOCUS + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_BeakBlastSetUp:: + setbeakblast BS_ATTACKER + printstring STRINGID_EMPTYSTRING3 + waitmessage 0x1 + playanimation BS_ATTACKER, B_ANIM_BEAK_BLAST_SETUP, NULL + printstring STRINGID_HEATUPBEAK + waitmessage 0x40 + end2 + +BattleScript_BeakBlastBurn:: + jumpifstatus BS_TARGET, STATUS1_BURN, BattleScript_AlreadyBurned + jumpiftype BS_TARGET, TYPE_FIRE, BattleScript_NotAffected + jumpifability BS_TARGET, ABILITY_WATER_VEIL, BattleScript_WaterVeilPrevents + jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_LeafGuardProtects + jumpifflowerveil BattleScript_FlowerVeilProtects + jumpifleafguard BattleScript_LeafGuardProtects + jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_BeakBlastBurnReturn + setmoveeffect MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER + seteffectprimary +BattleScript_BeakBlastBurnReturn: + return BattleScript_EffectCorrosiveGas:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON diff --git a/include/battle.h b/include/battle.h index 7212c4084..a86c6d34e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -144,6 +144,7 @@ struct ProtectStruct u32 usedThroatChopPreventedMove:1; u32 micle:1; u32 custap:1; // also quick claw + u32 beakBlastCharge:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 7ae55d01f..ffb824f0b 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -370,5 +370,7 @@ extern const u8 BattleScript_NotAffectedAbilityPopUp[]; extern const u8 BattleScript_BattlerShookOffTaunt[]; extern const u8 BattleScript_BattlerGotOverItsInfatuation[]; extern const u8 BattleScript_MeltedItem[]; +extern const u8 BattleScript_BeakBlastSetUp[]; +extern const u8 BattleScript_BeakBlastBurn[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index c04bc14f7..cfccef926 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -523,6 +523,7 @@ #define B_ANIM_SLIDE_OFFSCREEN 26 // for Emergency Exit #define B_ANIM_RESTORE_BG 27 // for Terrain Endings #define B_ANIM_TOTEM_FLARE 28 // Totem boosts aura flare +#define B_ANIM_BEAK_BLAST_SETUP 29 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index d88b34a53..1ccba4d43 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -358,7 +358,8 @@ #define EFFECT_METEOR_BEAM 352 #define EFFECT_RISING_VOLTAGE 353 #define EFFECT_CORROSIVE_GAS 354 +#define EFFECT_BEAK_BLAST 355 -#define NUM_BATTLE_MOVE_EFFECTS 355 +#define NUM_BATTLE_MOVE_EFFECTS 356 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index f35dbe2e3..ea96e6b4d 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -174,6 +174,7 @@ #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 #define VARIOUS_TRY_SET_CORROSIVE_GAS 105 +#define VARIOUS_SET_BEAK_BLAST 106 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 72f178de7..698b7e595 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -573,8 +573,9 @@ #define STRINGID_PKMNINSNAPTRAP 569 #define STRINGID_METEORBEAMCHARGING 570 #define STRINGID_ITEMMELTED 571 +#define STRINGID_HEATUPBEAK 572 -#define BATTLESTRINGS_COUNT 572 +#define BATTLESTRINGS_COUNT 573 // 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_main.c b/src/battle_main.c index 9cf56abf7..f053c13ef 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4598,13 +4598,19 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) { gActiveBattler = gBattlerAttacker = gBattleStruct->focusPunchBattlerId; gBattleStruct->focusPunchBattlerId++; - if (gChosenMoveByBattler[gActiveBattler] == MOVE_FOCUS_PUNCH - && !(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP) + if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP) && !(gDisableStructs[gBattlerAttacker].truantCounter) && !(gProtectStructs[gActiveBattler].noValidMoves)) { - BattleScriptExecute(BattleScript_FocusPunchSetUp); - return; + switch(gChosenMoveByBattler[gActiveBattler]) + { + case MOVE_FOCUS_PUNCH: + BattleScriptExecute(BattleScript_FocusPunchSetUp); + return; + case MOVE_BEAK_BLAST: + BattleScriptExecute(BattleScript_BeakBlastSetUp); + return; + } } } } diff --git a/src/battle_message.c b/src/battle_message.c index 4d1ae2ddb..d2ae86e13 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -699,9 +699,11 @@ static const u8 sText_PkmnShookOffTheTaunt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} got over\nits infatuation!"); 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!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_HEATUPBEAK - 12] = sText_HeatingUpBeak, [STRINGID_ITEMMELTED - 12] = sText_PkmnItemMelted, [STRINGID_METEORBEAMCHARGING - 12] = sText_MeteorBeamCharging, [STRINGID_PKMNINSNAPTRAP - 12] = sText_PkmnInSnapTrap, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9915654c5..0565f06d1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4807,6 +4807,12 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; effect = 1; } + else if (gProtectStructs[gBattlerTarget].beakBlastCharge) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BeakBlastBurn; + effect = 1; + } } gBattleScripting.moveendState++; break; @@ -7867,6 +7873,7 @@ static void Cmd_various(void) case MOVE_MIRROR_COAT: case MOVE_METAL_BURST: case MOVE_ME_FIRST: + case MOVE_BEAK_BLAST: gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); break; default: @@ -8457,6 +8464,9 @@ static void Cmd_various(void) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); } return; + case VARIOUS_SET_BEAK_BLAST: + gProtectStructs[gActiveBattler].beakBlastCharge = 1; + break; } gBattlescriptCurrInstr += 3; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 20449e446..2455b90cd 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10127,7 +10127,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEAK_BLAST] = { - .effect = EFFECT_PLACEHOLDER, + .effect = EFFECT_BEAK_BLAST, .power = 100, .type = TYPE_FLYING, .accuracy = 100, From 271f19e6cb0ad7450ac127d20865aee6fb8c3f32 Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 20:01:57 +0200 Subject: [PATCH 08/29] Terrain Pulse --- data/battle_scripts_1.s | 2 ++ include/constants/battle_move_effects.h | 3 ++- src/battle_main.c | 11 +++++++++++ src/battle_util.c | 4 ++++ src/data/battle_moves.h | 2 +- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 02da8a3bb..6f074b664 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -375,6 +375,7 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectRisingVoltage .4byte BattleScript_EffectCorrosiveGas .4byte BattleScript_EffectBeakBlast + .4byte BattleScript_EffectTerrainPulse BattleScript_EffectBeakBlast:: attackcanceler @@ -2196,6 +2197,7 @@ BattleScript_EffectBelch: BattleScript_EffectBodyPress: BattleScript_EffectExpandingForce: BattleScript_EffectRisingVoltage: +BattleScript_EffectTerrainPulse: BattleScript_HitFromAtkCanceler:: attackcanceler diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 1ccba4d43..d975da2fb 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -359,7 +359,8 @@ #define EFFECT_RISING_VOLTAGE 353 #define EFFECT_CORROSIVE_GAS 354 #define EFFECT_BEAK_BLAST 355 +#define EFFECT_TERRAIN_PULSE 356 -#define NUM_BATTLE_MOVE_EFFECTS 356 +#define NUM_BATTLE_MOVE_EFFECTS 357 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_main.c b/src/battle_main.c index f053c13ef..9f5105151 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5070,6 +5070,17 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) if (ItemId_GetPocket(gBattleMons[battlerAtk].item) == POCKET_BERRIES) gBattleStruct->dynamicMoveType = gNaturalGiftTable[ITEM_TO_BERRY(gBattleMons[battlerAtk].item)].type; } + else if (gBattleMoves[move].effect == EFFECT_TERRAIN_PULSE) + { + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_FAIRY | 0x80; + else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | 0x80; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_PSYCHIC | 0x80; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_GRASS | 0x80; + } attackerAbility = GetBattlerAbility(battlerAtk); GET_MOVE_TYPE(move, moveType); diff --git a/src/battle_util.c b/src/battle_util.c index 9d7453bab..1f0ef56ae 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7224,6 +7224,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) #endif basePower *= 2; break; + case EFFECT_TERRAIN_PULSE: + if (gFieldStatuses & (STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN)) + basePower *= 2; + break; } if (basePower == 0) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 2455b90cd..8bcdccc85 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11332,7 +11332,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_TERRAIN_PULSE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_TERRAIN_PULSE, .power = 50, .type = TYPE_NORMAL, .accuracy = 100, From 155e9b6332e505596e9308a71526d1a37c11ee62 Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 20:14:10 +0200 Subject: [PATCH 09/29] Court Change --- asm/macros/battle_script.inc | 4 + data/battle_scripts_1.s | 13 ++ include/constants/battle_move_effects.h | 3 +- include/constants/battle_script_commands.h | 1 + include/constants/battle_string_ids.h | 3 +- src/battle_message.c | 2 + src/battle_script_commands.c | 163 +++++++++++++++++++++ src/data/battle_moves.h | 2 +- 8 files changed, 188 insertions(+), 3 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 1405dd258..5cef3c769 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 6f074b664..bf501678c 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 d975da2fb..b6ad6e487 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 ea96e6b4d..8ae661af3 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 698b7e595..cfe25be1b 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 d2ae86e13..2a9d80424 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 0565f06d1..3e91205ac 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 8bcdccc85..6c8bdd7b7 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, From c2bd046ea670c7abf4b5fd827887bbdf6495060a Mon Sep 17 00:00:00 2001 From: Xhyzi Date: Tue, 15 Jun 2021 20:22:50 +0200 Subject: [PATCH 10/29] Shell Trap --- asm/macros/battle_script.inc | 13 +++++++ data/battle_anim_scripts.s | 5 +-- data/battle_scripts_1.s | 41 ++++++++++++++++++++++ include/battle.h | 1 + include/battle_scripts.h | 3 ++ include/constants/battle_anim.h | 1 + include/constants/battle_move_effects.h | 3 +- include/constants/battle_script_commands.h | 3 ++ include/constants/battle_string_ids.h | 3 +- src/battle_main.c | 3 ++ src/battle_message.c | 2 ++ src/data/battle_moves.h | 4 +-- 12 files changed, 76 insertions(+), 6 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 5cef3c769..6ae9fce29 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1782,6 +1782,19 @@ various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES .endm + .macro setshelltrap battler:req + various \battler, VARIOUS_SET_SHELL_TRAP + .endm + + .macro clearshelltrap battler:req + various \battler, VARIOUS_CLEAR_SHELL_TRAP + .endm + + .macro checkshelltrap battler:req, ptr:req + various \battler, VARIOUS_CHECK_SHELL_TRAP + .4byte \ptr + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index ee401010a..96dae719f 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -823,6 +823,7 @@ gBattleAnims_General:: .4byte General_RestoreBg @ B_ANIM_RESTORE_BG .4byte General_TotemFlare @ B_ANIM_TOTEM_FLARE .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP + .4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP .align 2 gBattleAnims_Special:: @@ -11831,8 +11832,7 @@ Move_AURORA_VEIL:: blendoff end -Move_SHELL_TRAP:: -ShellTrapChargeUp: +General_ShellTrapSetUp: loadspritegfx ANIM_TAG_SMALL_EMBER loadspritegfx ANIM_TAG_IMPACT monbg ANIM_TARGET @@ -11849,6 +11849,7 @@ ShellTrapChargeUp: clearmonbg ANIM_TARGET blendoff end +Move_SHELL_TRAP:: ShellTrapUnleash: loadspritegfx ANIM_TAG_IMPACT @pound loadspritegfx ANIM_TAG_SMALL_RED_EYE @red diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bf501678c..f64b42e51 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -377,6 +377,47 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectBeakBlast .4byte BattleScript_EffectTerrainPulse .4byte BattleScript_EffectCourtChange + .4byte BattleScript_EffectShellTrap + +BattleScript_EffectShellTrap:: + checkshelltrap BS_ATTACKER, BattleScript_MoveEnd + clearshelltrap BS_ATTACKER + attackcanceler + attackstring + goto BattleScript_ButItFailed + +BattleScript_ShellTrapSetUp:: + setshelltrap BS_ATTACKER + printstring STRINGID_EMPTYSTRING3 + waitmessage 0x1 + playanimation BS_ATTACKER B_ANIM_SHELL_TRAP_SETUP, NULL + printstring STRINGID_PREPARESHELLTRAP + waitmessage 0x40 + end2 + +BattleScript_ShellTrapExplode:: + clearshelltrap BS_ATTACKER + attackcanceler + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + resultmessage + waitmessage 0x40 + seteffectwithchance + tryfaintmon BS_TARGET, FALSE, NULL + moveendall + end BattleScript_EffectCourtChange:: attackcanceler diff --git a/include/battle.h b/include/battle.h index a86c6d34e..18e12fc18 100644 --- a/include/battle.h +++ b/include/battle.h @@ -145,6 +145,7 @@ struct ProtectStruct u32 micle:1; u32 custap:1; // also quick claw u32 beakBlastCharge:1; + u32 shellTrap:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index ffb824f0b..71a8a50a4 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -372,5 +372,8 @@ extern const u8 BattleScript_BattlerGotOverItsInfatuation[]; extern const u8 BattleScript_MeltedItem[]; extern const u8 BattleScript_BeakBlastSetUp[]; extern const u8 BattleScript_BeakBlastBurn[]; +extern const u8 BattleScript_ShellTrapSetUp[]; +extern const u8 BattleScript_ShellTrapExplode[]; +extern const u8 BattleScript_EffectShellTrap[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index cfccef926..c98007127 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -524,6 +524,7 @@ #define B_ANIM_RESTORE_BG 27 // for Terrain Endings #define B_ANIM_TOTEM_FLARE 28 // Totem boosts aura flare #define B_ANIM_BEAK_BLAST_SETUP 29 +#define B_ANIM_SHELL_TRAP_SETUP 30 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index b6ad6e487..cc5e94acd 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -361,7 +361,8 @@ #define EFFECT_BEAK_BLAST 355 #define EFFECT_TERRAIN_PULSE 356 #define EFFECT_COURT_CHANGE 357 +#define EFFECT_SHELL_TRAP 358 -#define NUM_BATTLE_MOVE_EFFECTS 358 +#define NUM_BATTLE_MOVE_EFFECTS 359 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 8ae661af3..6e67bd954 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -176,6 +176,9 @@ #define VARIOUS_TRY_SET_CORROSIVE_GAS 105 #define VARIOUS_SET_BEAK_BLAST 106 #define VARIOUS_SWAP_SIDE_STATUSES 107 +#define VARIOUS_SET_SHELL_TRAP 108 +#define VARIOUS_CLEAR_SHELL_TRAP 109 +#define VARIOUS_CHECK_SHELL_TRAP 110 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index cfe25be1b..823164717 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -575,8 +575,9 @@ #define STRINGID_ITEMMELTED 571 #define STRINGID_HEATUPBEAK 572 #define STRINGID_COURTCHANGE 573 +#define STRINGID_PREPARESHELLTRAP 574 -#define BATTLESTRINGS_COUNT 574 +#define BATTLESTRINGS_COUNT 575 // 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_main.c b/src/battle_main.c index 9f5105151..223188652 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4610,6 +4610,9 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) case MOVE_BEAK_BLAST: BattleScriptExecute(BattleScript_BeakBlastSetUp); return; + case MOVE_SHELL_TRAP: + BattleScriptExecute(BattleScript_ShellTrapSetUp); + return; } } } diff --git a/src/battle_message.c b/src/battle_message.c index 2a9d80424..6d39cf84c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -701,9 +701,11 @@ static const u8 sText_MeteorBeamCharging[] = _("{B_ATK_NAME_WITH_PREFIX} is over 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!"); +static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set\n a shell trap!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_PREPARESHELLTRAP - 12] = sText_PrepareShellTrap, [STRINGID_COURTCHANGE - 12] = sText_CourtChange, [STRINGID_HEATUPBEAK - 12] = sText_HeatingUpBeak, [STRINGID_ITEMMELTED - 12] = sText_PkmnItemMelted, diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 6c8bdd7b7..abcd8a100 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10197,13 +10197,13 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SHELL_TRAP] = { - .effect = EFFECT_PLACEHOLDER, + .effect = EFFECT_SHELL_TRAP, .power = 150, .type = TYPE_FIRE, .accuracy = 100, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_SELECTED, + .target = MOVE_TARGET_OPPONENTS_FIELD, .priority = -3, .flags = FLAG_PROTECT_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .split = SPLIT_SPECIAL, From 86efd69370e9a646f89626c126c092017b71518e Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Fri, 19 Nov 2021 20:19:10 +1300 Subject: [PATCH 11/29] Finish/fix Beak Blast This was not working at all, but the basic framework was there; some small changes tidied it up and made it work. --- data/battle_scripts_1.s | 26 ++++++-------------------- src/battle_script_commands.c | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c98b35b5e..8f898f1d2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -403,12 +403,12 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectOctolock @ EFFECT_OCTOLOCK .4byte BattleScript_EffectClangorousSoul @ EFFECT_CLANGOROUS_SOUL .4byte BattleScript_EffectHit @ EFFECT_BOLT_BEAK - .4byte BattleScript_EffectHit @ EFFECT_EXPANDING_FORCE + .4byte BattleScript_EffectHit @ EFFECT_EXPANDING_FORCE .4byte BattleScript_EffectScaleShot @ EFFECT_SCALE_SHOT .4byte BattleScript_EffectMeteorBeam @ EFFECT_METEOR_BEAM .4byte BattleScript_EffectHit @ EFFECT_RISING_VOLTAGE .4byte BattleScript_EffectCorrosiveGas @ EFFECT_CORROSIVE_GAS - .4byte BattleScript_EffectBeakBlast @ EFFECT_BEAK_BLAST + .4byte BattleScript_EffectHit @ EFFECT_BEAK_BLAST .4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE .4byte BattleScript_EffectShellTrap @ EFFECT_SHELL_TRAP @@ -464,14 +464,6 @@ BattleScript_EffectCourtChange:: waitmessage 0x40 goto BattleScript_MoveEnd -BattleScript_EffectBeakBlast:: - attackcanceler - jumpifnodamage BattleScript_HitFromAccCheck - ppreduce - printstring STRINGID_PKMNLOSTFOCUS - waitmessage 0x40 - goto BattleScript_MoveEnd - BattleScript_BeakBlastSetUp:: setbeakblast BS_ATTACKER printstring STRINGID_EMPTYSTRING3 @@ -482,17 +474,11 @@ BattleScript_BeakBlastSetUp:: end2 BattleScript_BeakBlastBurn:: - jumpifstatus BS_TARGET, STATUS1_BURN, BattleScript_AlreadyBurned - jumpiftype BS_TARGET, TYPE_FIRE, BattleScript_NotAffected - jumpifability BS_TARGET, ABILITY_WATER_VEIL, BattleScript_WaterVeilPrevents - jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_LeafGuardProtects - jumpifflowerveil BattleScript_FlowerVeilProtects - jumpifleafguardprotected BS_TARGET, BattleScript_LeafGuardProtects - jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_BeakBlastBurnReturn - setmoveeffect MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER - seteffectprimary -BattleScript_BeakBlastBurnReturn: + setbyte cMULTISTRING_CHOOSER, 0 + copybyte gEffectBattler, gBattlerAttacker + call BattleScript_MoveEffectBurn return + BattleScript_EffectCorrosiveGas:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b767b871e..232b97697 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1543,6 +1543,11 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr++; } + else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; + gBattlescriptCurrInstr++; + } else { gBattlescriptCurrInstr++; @@ -4964,7 +4969,7 @@ static void Cmd_moveend(void) } else if (gProtectStructs[gBattlerTarget].obstructed && gCurrentMove != MOVE_SUCKER_PUNCH) { - gProtectStructs[gBattlerAttacker].touchedProtectLike = 0; + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; i = gBattlerAttacker; gBattlerAttacker = gBattlerTarget; gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable @@ -4973,8 +4978,13 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; effect = 1; } - else if (gProtectStructs[gBattlerTarget].beakBlastCharge) + // Not strictly a protect effect, but works the same way + else if (gProtectStructs[gBattlerTarget].beakBlastCharge + && CanBeBurned(gBattlerAttacker) + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + gBattleMons[gBattlerAttacker].status1 = STATUS1_BURN; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_BeakBlastBurn; effect = 1; @@ -9317,7 +9327,7 @@ static void Cmd_various(void) } } case VARIOUS_SET_BEAK_BLAST: - gProtectStructs[gActiveBattler].beakBlastCharge = 1; + gProtectStructs[gBattlerAttacker].beakBlastCharge = 1; break; case VARIOUS_SWAP_SIDE_STATUSES: { From 48c91d03cdfd5f9e742ef67b0be43fb1c8c2688a Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Fri, 19 Nov 2021 20:20:16 +1300 Subject: [PATCH 12/29] Fix terrain checks on DLC moves Expanding Force and Rising Voltage now boost damage correctly. Expanding Force doesn't hit both targets yet however. --- src/battle_util.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index cbc96ae56..e946fe8f0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7262,6 +7262,9 @@ u32 GetMoveTarget(u16 move, u8 setTarget) // Special cases if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) moveTarget = MOVE_TARGET_USER; + + if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN)) + moveTarget = MOVE_TARGET_BOTH; switch (moveTarget) { @@ -7991,18 +7994,12 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; break; case EFFECT_EXPANDING_FORCE: - if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) - basePower = 120; + if (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN)) + MulModifier(&basePower, UQ_4_12(1.5)); break; case EFFECT_RISING_VOLTAGE: - #ifdef ITEM_EXPANSION //Air Balloon exception with item expansion branch - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING) - && gBattleMons[battlerDef].item != ITEM_AIR_BALLOON && gBattleMons[battlerDef].ability != ABILITY_LEVITATE) - #else - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING) - && gBattleMons[battlerDef].ability != ABILITY_LEVITATE) - #endif - basePower *= 2; + if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + basePower *= 2; break; } From 14a2e863139d4726a24b9b32ef49e3e85743c628 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Fri, 19 Nov 2021 21:57:32 +1300 Subject: [PATCH 13/29] Fix Scale Shot Lowers defense and raises speed instead of just lowering defense now. Tested with Contrary and min/max speed/def. --- data/battle_scripts_1.s | 24 +++++++++++++++++++++--- include/battle_scripts.h | 1 + include/constants/battle.h | 4 ++-- src/battle_main.c | 4 ++-- src/battle_script_commands.c | 7 +++++++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8f898f1d2..d5d5707ff 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -570,9 +570,7 @@ BattleScript_ScaleShotPrintStrings:: printstring STRINGID_HITXTIMES waitmessage 0x40 BattleScript_ScaleShotEnd:: - setmoveeffect MOVE_EFFECT_SPD_PLUS_1 | MOVE_EFFECT_AFFECTS_USER - seteffectwithchance - setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER + setmoveeffect MOVE_EFFECT_SCALE_SHOT | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN seteffectwithchance tryfaintmon BS_TARGET, FALSE, NULL moveendcase MOVEEND_SYNCHRONIZE_TARGET @@ -7182,6 +7180,26 @@ BattleScript_DefSpDefDownTrySpDef:: BattleScript_DefSpDefDownRet:: return +BattleScript_DefDownSpeedUp:: + jumpifstat BS_ATTACKER, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_DefDownSpeedUpTryDef + jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_DefDownSpeedUpRet +BattleScript_DefDownSpeedUpTryDef:: + playstatchangeanimation BS_ATTACKER, BIT_DEF, STAT_CHANGE_NEGATIVE | STAT_CHANGE_CANT_PREVENT + setstatchanger STAT_DEF, 1, TRUE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_DefDownSpeedUpTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpTrySpeed + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_DefDownSpeedUpTrySpeed: + playstatchangeanimation BS_ATTACKER, BIT_SPEED, 0 + setstatchanger STAT_SPEED, 1, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_DefDownSpeedUpRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpRet + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_DefDownSpeedUpRet:: + return + BattleScript_KnockedOff:: playanimation BS_TARGET, B_ANIM_ITEM_KNOCKOFF, NULL printstring STRINGID_PKMNKNOCKEDOFF diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 1c130b90f..7dfc1a6da 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -421,5 +421,6 @@ extern const u8 BattleScript_BeakBlastBurn[]; extern const u8 BattleScript_ShellTrapSetUp[]; extern const u8 BattleScript_ShellTrapExplode[]; extern const u8 BattleScript_EffectShellTrap[]; +extern const u8 BattleScript_DefDownSpeedUp[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 515d4ac02..46b6494b2 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -359,9 +359,9 @@ #define MOVE_EFFECT_RECOIL_HP_25 0x46 #define MOVE_EFFECT_RELIC_SONG 0x47 #define MOVE_EFFECT_TRAP_BOTH 0x48 -#define MOVE_EFFECT_SPD_PLUS_1_DEF_MINUS_1 0x49 +#define MOVE_EFFECT_SCALE_SHOT 0x49 #define MOVE_EFFECT_MELT_ITEM 0x4A -#define NUM_MOVE_EFFECTS 0x50 +#define NUM_MOVE_EFFECTS 0x4B #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/src/battle_main.c b/src/battle_main.c index c39407653..25ac66be5 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4715,8 +4715,8 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) BattleScriptExecute(BattleScript_BeakBlastSetUp); return; case MOVE_SHELL_TRAP: - BattleScriptExecute(BattleScript_ShellTrapSetUp); - return; + BattleScriptExecute(BattleScript_ShellTrapSetUp); + return; } } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 232b97697..0aa068a99 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3489,6 +3489,10 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION; break; + case MOVE_EFFECT_SCALE_SHOT: + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_DefDownSpeedUp; + break; } } } @@ -9329,6 +9333,9 @@ static void Cmd_various(void) case VARIOUS_SET_BEAK_BLAST: gProtectStructs[gBattlerAttacker].beakBlastCharge = 1; break; + case VARIOUS_SET_SHELL_TRAP: + gProtectStructs[gBattlerAttacker].shellTrap = 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 From bcaa17ffb31182c17c7a56134f4380bf52c33562 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 21 Nov 2021 17:20:45 +1300 Subject: [PATCH 14/29] Finish/tidy up Court Change Use a macro to simplify timer and status updates, and swap things like reflectBattlerId to the opposing side - this is required for the effects to be properly swapped. --- include/battle.h | 7 +- src/battle_script_commands.c | 216 +++++++++-------------------------- 2 files changed, 59 insertions(+), 164 deletions(-) diff --git a/include/battle.h b/include/battle.h index 596130bfe..fbeb3ffb1 100644 --- a/include/battle.h +++ b/include/battle.h @@ -208,9 +208,6 @@ struct SideTimer u8 mistBattlerId; u8 safeguardTimer; u8 safeguardBattlerId; - u8 followmeTimer; - u8 followmeTarget:3; - u8 followmePowder:1; // Rage powder, does not affect grass type pokemon. u8 spikesAmount; u8 toxicSpikesAmount; u8 stealthRockAmount; @@ -221,6 +218,10 @@ struct SideTimer u8 tailwindBattlerId; u8 luckyChantTimer; u8 luckyChantBattlerId; + // Timers below this point are not swapped by Court Change + u8 followmeTimer; + u8 followmeTarget:3; + u8 followmePowder:1; // Rage powder, does not affect grass type pokemon. u8 retaliateTimer; }; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0aa068a99..b17a7555b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7527,6 +7527,60 @@ static bool32 IsRototillerAffected(u32 battlerId) return TRUE; } +#define COURTCHANGE_SWAP(status, structField, temp) \ +{ \ + temp = gSideStatuses[0]; \ + if (gSideStatuses[1] & status) \ + gSideStatuses[0] |= status; \ + else \ + gSideStatuses[0] &= ~(status); \ + if (temp & status) \ + gSideStatuses[1] |= status; \ + else \ + gSideStatuses[1] &= ~(status); \ + SWAP(sideTimer0->structField, sideTimer1->structField, temp);\ +} \ + +#define UPDATE_COURTCHANGED_BATTLER(structField)\ +{ \ + sideTimer0->structField ^= BIT_SIDE; \ + sideTimer1->structField ^= BIT_SIDE; \ +} \ + +static bool32 CourtChangeSwapSideStatuses(void) +{ + struct SideTimer *sideTimer0 = &gSideTimers[0]; + struct SideTimer *sideTimer1 = &gSideTimers[1]; + u32 temp; + + // TODO: add Pledge-related effects + // TODO: add Gigantamax-related effects + + // Swap timers and statuses + COURTCHANGE_SWAP(SIDE_STATUS_REFLECT, reflectTimer, temp) + COURTCHANGE_SWAP(SIDE_STATUS_LIGHTSCREEN, lightscreenTimer, temp) + COURTCHANGE_SWAP(SIDE_STATUS_MIST, mistTimer, temp); + COURTCHANGE_SWAP(SIDE_STATUS_SAFEGUARD, safeguardTimer, temp); + COURTCHANGE_SWAP(SIDE_STATUS_AURORA_VEIL, auroraVeilTimer, temp); + COURTCHANGE_SWAP(SIDE_STATUS_TAILWIND, tailwindTimer, temp); + // Lucky Chant doesn't exist in gen 8, but seems like it should be affected by Court Change + COURTCHANGE_SWAP(SIDE_STATUS_LUCKY_CHANT, luckyChantTimer, temp); + COURTCHANGE_SWAP(SIDE_STATUS_SPIKES, spikesAmount, temp); + COURTCHANGE_SWAP(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, temp); + COURTCHANGE_SWAP(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, temp); + COURTCHANGE_SWAP(SIDE_STATUS_STICKY_WEB, stickyWebAmount, temp); + + // Change battler IDs of swapped effects. Needed for the correct string when they expire + // E.g. "Foe's Reflect wore off!" + UPDATE_COURTCHANGED_BATTLER(reflectBattlerId); + UPDATE_COURTCHANGED_BATTLER(lightscreenBattlerId); + UPDATE_COURTCHANGED_BATTLER(mistBattlerId); + UPDATE_COURTCHANGED_BATTLER(safeguardBattlerId); + UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId); + UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId); + UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId); +} + static void Cmd_various(void) { struct Pokemon *mon; @@ -9338,167 +9392,7 @@ static void Cmd_various(void) 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; + CourtChangeSwapSideStatuses(); break; } } // End of switch (gBattlescriptCurrInstr[2]) From abb67e96e8b6de05b9364bc02cd71b8a33abe6b3 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 21 Nov 2021 21:49:47 +1300 Subject: [PATCH 15/29] Finish Expanding Force Hits both foes if the user is affected by Psychic Terrain. Modified targeting is also shown in the move selection screen. --- src/battle_controller_player.c | 7 +++++++ src/battle_script_commands.c | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index e1cb2f54f..a970c38b7 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -609,6 +609,13 @@ static void HandleInputChooseMove(void) else moveTarget = MOVE_TARGET_SELECTED; } + else if (moveInfo->moves[gMoveSelectionCursor[gActiveBattler]] == MOVE_EXPANDING_FORCE) + { + if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN)) + moveTarget = MOVE_TARGET_BOTH; + else + moveTarget = MOVE_TARGET_SELECTED; + } else { moveTarget = gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].target; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b17a7555b..31a2d4fc6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5246,7 +5246,9 @@ static void Cmd_moveend(void) if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !gProtectStructs[gBattlerAttacker].chargingTurn - && (gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH || gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY) + && (gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH + || gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY + || (gBattleMoves[gCurrentMove].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN))) && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) { u8 battlerId; From 70f0018c08c1ad9028e65b13ae1bc178177b460d Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 22 Nov 2021 14:14:41 +1300 Subject: [PATCH 16/29] Partially implement Shell Trap Doesn't play the animation when the trap triggers, but kinda works? May also be incredibly buggy, but I'm not interested in working on this move any further. --- asm/macros/battle_script.inc | 5 +++-- data/battle_scripts_1.s | 2 +- include/battle.h | 13 ++++++------ src/battle_script_commands.c | 38 ++++++++++++++++++++++++++++++++---- src/data/battle_moves.h | 2 +- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index cf2045eb6..2498bce64 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1946,9 +1946,10 @@ various \battler, VARIOUS_CLEAR_SHELL_TRAP .endm - .macro checkshelltrap battler:req, ptr:req + .macro checkshelltrap battler:req, ptr1:req, ptr2:req various \battler, VARIOUS_CHECK_SHELL_TRAP - .4byte \ptr + .4byte \ptr1 + .4byte \ptr2 .endm @ helpful macros diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d5d5707ff..e453e3705 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -413,7 +413,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectShellTrap @ EFFECT_SHELL_TRAP BattleScript_EffectShellTrap:: - checkshelltrap BS_ATTACKER, BattleScript_MoveEnd + checkshelltrap BS_ATTACKER, BattleScript_ShellTrapExplode, BattleScript_MoveEnd clearshelltrap BS_ATTACKER attackcanceler attackstring diff --git a/include/battle.h b/include/battle.h index fbeb3ffb1..ad7924017 100644 --- a/include/battle.h +++ b/include/battle.h @@ -153,12 +153,13 @@ struct ProtectStruct u32 usedCustapBerry:1; // also quick claw u32 touchedProtectLike:1; // End of 32-bit bitfield - u8 disableEjectPack:1; - u8 statFell:1; - u8 pranksterElevated:1; - u8 quickDraw:1; - u8 beakBlastCharge:1; - u8 shellTrap:1; + u16 disableEjectPack:1; + u16 statFell:1; + u16 pranksterElevated:1; + u16 quickDraw:1; + u16 beakBlastCharge:1; + u16 shellTrapSet:1; + u16 shellTrapTriggered:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 31a2d4fc6..aa3c85375 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1543,7 +1543,8 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr++; } - else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + else if ((gProtectStructs[gBattlerTarget].beakBlastCharge || gProtectStructs[gBattlerTarget].shellTrapSet) + && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; gBattlescriptCurrInstr++; @@ -4983,7 +4984,7 @@ static void Cmd_moveend(void) effect = 1; } // Not strictly a protect effect, but works the same way - else if (gProtectStructs[gBattlerTarget].beakBlastCharge + else if (gProtectStructs[gBattlerTarget].beakBlastCharge && CanBeBurned(gBattlerAttacker) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { @@ -4993,6 +4994,21 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_BeakBlastBurn; effect = 1; } + else if (gProtectStructs[gBattlerTarget].shellTrapSet + && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + { + u32 temp; + gProtectStructs[gBattlerTarget].shellTrapTriggered = TRUE; + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + // Swap battlers so target attacks attacker with Shell Trap + SWAP(gBattlerAttacker, gBattlerTarget, temp); + // Set current move to Shell Trap + gCurrentMove = MOVE_SHELL_TRAP; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EffectShellTrap; + effect = TRUE; + } } gBattleScripting.moveendState++; break; @@ -9387,10 +9403,24 @@ static void Cmd_various(void) } } case VARIOUS_SET_BEAK_BLAST: - gProtectStructs[gBattlerAttacker].beakBlastCharge = 1; + gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; break; case VARIOUS_SET_SHELL_TRAP: - gProtectStructs[gBattlerAttacker].shellTrap = 1; + gProtectStructs[gBattlerAttacker].shellTrapSet = TRUE; + break; + case VARIOUS_CLEAR_SHELL_TRAP: + gProtectStructs[gBattlerAttacker].shellTrapSet = FALSE; + break; + case VARIOUS_CHECK_SHELL_TRAP: + // Attack with Shell Trap + if (gProtectStructs[gBattlerAttacker].shellTrapSet == TRUE && gProtectStructs[gBattlerAttacker].shellTrapTriggered == TRUE) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + // Attacked with Shell Trap, go to move end + else if (gProtectStructs[gBattlerAttacker].shellTrapSet == FALSE && gProtectStructs[gBattlerAttacker].shellTrapTriggered == TRUE) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7); + // Shell Trap failed + else + gBattlescriptCurrInstr += 11; break; case VARIOUS_SWAP_SIDE_STATUSES: { diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index bf591dac4..62c0595a6 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10218,7 +10218,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 100, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_OPPONENTS_FIELD, + .target = MOVE_TARGET_BOTH, .priority = -3, .flags = FLAG_PROTECT_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, .split = SPLIT_SPECIAL, From 42b8f18cb1fa9a1d29e8ecd9844b6a6bf54acf6b Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 22 Nov 2021 14:35:01 +1300 Subject: [PATCH 17/29] Remove Corrosive Gas code This was not working at all in testing, so it can be done by a separate PR later. --- asm/macros/battle_script.inc | 5 ----- data/battle_scripts_1.s | 19 ------------------ include/constants/battle_move_effects.h | 9 ++++----- src/battle_script_commands.c | 26 ------------------------- src/data/battle_moves.h | 2 +- 5 files changed, 5 insertions(+), 56 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 2498bce64..500ec0919 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1925,11 +1925,6 @@ various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK .endm - .macro trysetcorrosivegas battler:req, ptr:req - various \battler, VARIOUS_TRY_SET_CORROSIVE_GAS - .4byte \ptr - .endm - .macro setbeakblast battler:req various \battler, VARIOUS_SET_BEAK_BLAST .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e453e3705..99e3ad462 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -407,7 +407,6 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectScaleShot @ EFFECT_SCALE_SHOT .4byte BattleScript_EffectMeteorBeam @ EFFECT_METEOR_BEAM .4byte BattleScript_EffectHit @ EFFECT_RISING_VOLTAGE - .4byte BattleScript_EffectCorrosiveGas @ EFFECT_CORROSIVE_GAS .4byte BattleScript_EffectHit @ EFFECT_BEAK_BLAST .4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE .4byte BattleScript_EffectShellTrap @ EFFECT_SHELL_TRAP @@ -479,24 +478,6 @@ BattleScript_BeakBlastBurn:: call BattleScript_MoveEffectBurn return -BattleScript_EffectCorrosiveGas:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce - jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_PrintMoveMissed - trysetcorrosivegas BS_TARGET, BattleScript_ButItFailed - attackanimation - waitanimation - printstring STRINGID_ITEMMELTED - waitmessage 0x40 - goto BattleScript_MoveEnd - -BattleScript_MeltedItem:: - printstring STRINGID_ITEMMELTED - waitmessage 0x40 - return - BattleScript_EffectMeteorBeam:: @ DecideTurn jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 5c6826394..0df43c060 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -390,11 +390,10 @@ #define EFFECT_SCALE_SHOT 384 #define EFFECT_METEOR_BEAM 385 #define EFFECT_RISING_VOLTAGE 386 -#define EFFECT_CORROSIVE_GAS 387 -#define EFFECT_BEAK_BLAST 388 -#define EFFECT_COURT_CHANGE 389 -#define EFFECT_SHELL_TRAP 390 +#define EFFECT_BEAK_BLAST 387 +#define EFFECT_COURT_CHANGE 388 +#define EFFECT_SHELL_TRAP 389 -#define NUM_BATTLE_MOVE_EFFECTS 391 +#define NUM_BATTLE_MOVE_EFFECTS 390 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index aa3c85375..6d65bbd62 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9376,32 +9376,6 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; return; } - case VARIOUS_TRY_SET_CORROSIVE_GAS: - { - if (gBattleMons[gActiveBattler].item != 0 - && CanBattlerGetOrLoseItem(gActiveBattler, gBattleMons[gActiveBattler].item) - && !NoAliveMonsForEitherParty()) - { - if (GetBattlerAbility(gActiveBattler) == ABILITY_STICKY_HOLD && IsBattlerAlive(gActiveBattler)) - { - gBattlerAbility = gActiveBattler; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; - } - else - { // Item is melted normally - u32 side = GetBattlerSide(gActiveBattler); - - gLastUsedItem = gBattleMons[gActiveBattler].item; - gBattleMons[gActiveBattler].item = 0; - gBattleStruct->choicedMove[gActiveBattler] = 0; - gWishFutureKnock.meltedItemMons[side] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]]; - - CheckSetUnburden(gActiveBattler); - gBattlescriptCurrInstr += 7; - } - } - } case VARIOUS_SET_BEAK_BLAST: gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; break; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 62c0595a6..57b9bce4f 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11417,7 +11417,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_CORROSIVE_GAS] = { - .effect = EFFECT_CORROSIVE_GAS, + .effect = EFFECT_PLACEHOLDER, // EFFECT_CORROSIVE_GAS, TODO .power = 0, .type = TYPE_POISON, .accuracy = 100, From d2eb5f0e6191645a677ae2c8ebcdde3937237c68 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 22 Nov 2021 14:46:47 +1300 Subject: [PATCH 18/29] Remove shell trap effect code Left strings and animations as those were fine, but code was non-functional and fixing it was not trivial. --- asm/macros/battle_script.inc | 14 -------- data/battle_scripts_1.s | 41 ---------------------- include/battle.h | 2 -- include/battle_scripts.h | 3 -- include/constants/battle_move_effects.h | 1 - include/constants/battle_script_commands.h | 3 -- src/battle_main.c | 3 -- src/battle_script_commands.c | 35 +----------------- src/data/battle_moves.h | 2 +- 9 files changed, 2 insertions(+), 102 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 500ec0919..a65ccaf44 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1933,20 +1933,6 @@ various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES .endm - .macro setshelltrap battler:req - various \battler, VARIOUS_SET_SHELL_TRAP - .endm - - .macro clearshelltrap battler:req - various \battler, VARIOUS_CLEAR_SHELL_TRAP - .endm - - .macro checkshelltrap battler:req, ptr1:req, ptr2:req - various \battler, VARIOUS_CHECK_SHELL_TRAP - .4byte \ptr1 - .4byte \ptr2 - .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 99e3ad462..eeeba7cf7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -409,47 +409,6 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHit @ EFFECT_RISING_VOLTAGE .4byte BattleScript_EffectHit @ EFFECT_BEAK_BLAST .4byte BattleScript_EffectCourtChange @ EFFECT_COURT_CHANGE - .4byte BattleScript_EffectShellTrap @ EFFECT_SHELL_TRAP - -BattleScript_EffectShellTrap:: - checkshelltrap BS_ATTACKER, BattleScript_ShellTrapExplode, BattleScript_MoveEnd - clearshelltrap BS_ATTACKER - attackcanceler - attackstring - goto BattleScript_ButItFailed - -BattleScript_ShellTrapSetUp:: - setshelltrap BS_ATTACKER - printstring STRINGID_EMPTYSTRING3 - waitmessage 0x1 - playanimation BS_ATTACKER B_ANIM_SHELL_TRAP_SETUP, NULL - printstring STRINGID_PREPARESHELLTRAP - waitmessage 0x40 - end2 - -BattleScript_ShellTrapExplode:: - clearshelltrap BS_ATTACKER - attackcanceler - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage 0x40 - resultmessage - waitmessage 0x40 - seteffectwithchance - tryfaintmon BS_TARGET, FALSE, NULL - moveendall - end BattleScript_EffectCourtChange:: attackcanceler diff --git a/include/battle.h b/include/battle.h index ad7924017..69161ba6f 100644 --- a/include/battle.h +++ b/include/battle.h @@ -158,8 +158,6 @@ struct ProtectStruct u16 pranksterElevated:1; u16 quickDraw:1; u16 beakBlastCharge:1; - u16 shellTrapSet:1; - u16 shellTrapTriggered:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 7dfc1a6da..ec1dbb23c 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -418,9 +418,6 @@ extern const u8 BattleScript_NeutralizingGasExits[]; extern const u8 BattleScript_MeltedItem[]; extern const u8 BattleScript_BeakBlastSetUp[]; extern const u8 BattleScript_BeakBlastBurn[]; -extern const u8 BattleScript_ShellTrapSetUp[]; -extern const u8 BattleScript_ShellTrapExplode[]; -extern const u8 BattleScript_EffectShellTrap[]; extern const u8 BattleScript_DefDownSpeedUp[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 0df43c060..c6afed12c 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -392,7 +392,6 @@ #define EFFECT_RISING_VOLTAGE 386 #define EFFECT_BEAK_BLAST 387 #define EFFECT_COURT_CHANGE 388 -#define EFFECT_SHELL_TRAP 389 #define NUM_BATTLE_MOVE_EFFECTS 390 diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 977a69dbf..897bf35fb 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -211,9 +211,6 @@ #define VARIOUS_TRY_SET_CORROSIVE_GAS 138 #define VARIOUS_SET_BEAK_BLAST 139 #define VARIOUS_SWAP_SIDE_STATUSES 140 -#define VARIOUS_SET_SHELL_TRAP 141 -#define VARIOUS_CLEAR_SHELL_TRAP 142 -#define VARIOUS_CHECK_SHELL_TRAP 143 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_main.c b/src/battle_main.c index 25ac66be5..1c2d37dbc 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4714,9 +4714,6 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) case MOVE_BEAK_BLAST: BattleScriptExecute(BattleScript_BeakBlastSetUp); return; - case MOVE_SHELL_TRAP: - BattleScriptExecute(BattleScript_ShellTrapSetUp); - return; } } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6d65bbd62..a58aeed64 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1543,8 +1543,7 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr++; } - else if ((gProtectStructs[gBattlerTarget].beakBlastCharge || gProtectStructs[gBattlerTarget].shellTrapSet) - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; gBattlescriptCurrInstr++; @@ -4994,21 +4993,6 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_BeakBlastBurn; effect = 1; } - else if (gProtectStructs[gBattlerTarget].shellTrapSet - && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) - { - u32 temp; - gProtectStructs[gBattlerTarget].shellTrapTriggered = TRUE; - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - // Swap battlers so target attacks attacker with Shell Trap - SWAP(gBattlerAttacker, gBattlerTarget, temp); - // Set current move to Shell Trap - gCurrentMove = MOVE_SHELL_TRAP; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_EffectShellTrap; - effect = TRUE; - } } gBattleScripting.moveendState++; break; @@ -9379,23 +9363,6 @@ static void Cmd_various(void) case VARIOUS_SET_BEAK_BLAST: gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; break; - case VARIOUS_SET_SHELL_TRAP: - gProtectStructs[gBattlerAttacker].shellTrapSet = TRUE; - break; - case VARIOUS_CLEAR_SHELL_TRAP: - gProtectStructs[gBattlerAttacker].shellTrapSet = FALSE; - break; - case VARIOUS_CHECK_SHELL_TRAP: - // Attack with Shell Trap - if (gProtectStructs[gBattlerAttacker].shellTrapSet == TRUE && gProtectStructs[gBattlerAttacker].shellTrapTriggered == TRUE) - gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); - // Attacked with Shell Trap, go to move end - else if (gProtectStructs[gBattlerAttacker].shellTrapSet == FALSE && gProtectStructs[gBattlerAttacker].shellTrapTriggered == TRUE) - gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7); - // Shell Trap failed - else - gBattlescriptCurrInstr += 11; - break; case VARIOUS_SWAP_SIDE_STATUSES: { CourtChangeSwapSideStatuses(); diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 57b9bce4f..26c77a8e3 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10212,7 +10212,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SHELL_TRAP] = { - .effect = EFFECT_SHELL_TRAP, + .effect = EFFECT_PLACEHOLDER, // EFFECT_SHELL_TRAP, .power = 150, .type = TYPE_FIRE, .accuracy = 100, From 50d0cd52e8992869adb1cd5be680d9a90825e9d2 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 22 Nov 2021 15:13:54 +1300 Subject: [PATCH 19/29] Clean up Corrosive Gas Remove code and unused move effect. --- include/battle.h | 1 - include/battle_scripts.h | 1 - include/constants/battle.h | 3 +-- src/battle_script_commands.c | 14 +++----------- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/include/battle.h b/include/battle.h index 69161ba6f..9192d4ed3 100644 --- a/include/battle.h +++ b/include/battle.h @@ -245,7 +245,6 @@ struct WishFutureKnock u8 wishMonId[MAX_BATTLERS_COUNT]; u8 weatherDuration; u8 knockedOffMons[2]; // Each battler is represented by a bit. The array entry is dependent on the battler's side. - u8 meltedItemMons[2]; // Same as above }; struct AI_SavedBattleMon diff --git a/include/battle_scripts.h b/include/battle_scripts.h index ec1dbb23c..2f98ef7a1 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -415,7 +415,6 @@ extern const u8 BattleScript_AttackerFormChangeMoveEffect[]; extern const u8 BattleScript_BothCanNoLongerEscape[]; extern const u8 BattleScript_OctolockEndTurn[]; extern const u8 BattleScript_NeutralizingGasExits[]; -extern const u8 BattleScript_MeltedItem[]; extern const u8 BattleScript_BeakBlastSetUp[]; extern const u8 BattleScript_BeakBlastBurn[]; extern const u8 BattleScript_DefDownSpeedUp[]; diff --git a/include/constants/battle.h b/include/constants/battle.h index 46b6494b2..f615be05f 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -360,8 +360,7 @@ #define MOVE_EFFECT_RELIC_SONG 0x47 #define MOVE_EFFECT_TRAP_BOTH 0x48 #define MOVE_EFFECT_SCALE_SHOT 0x49 -#define MOVE_EFFECT_MELT_ITEM 0x4A -#define NUM_MOVE_EFFECTS 0x4B +#define NUM_MOVE_EFFECTS 0x4A #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a58aeed64..8e2c59d8a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3160,8 +3160,7 @@ void SetMoveEffect(bool32 primary, u32 certain) | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_SECRET_BASE)) - && (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] - || gWishFutureKnock.meltedItemMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]])) + && (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]])) { gBattlescriptCurrInstr++; } @@ -5583,11 +5582,6 @@ static void Cmd_switchindataupdate(void) { gBattleMons[gActiveBattler].item = 0; } - // check melted items - if (gWishFutureKnock.meltedItemMons[i] & gBitTable[gBattlerPartyIndexes[gActiveBattler]]) - { - gBattleMons[gActiveBattler].item = 0; - } if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS) { @@ -12305,16 +12299,14 @@ static void Cmd_tryswapitems(void) // trick u8 sideAttacker = GetBattlerSide(gBattlerAttacker); u8 sideTarget = GetBattlerSide(gBattlerTarget); - // you can't swap items if they were knocked off or melted in regular battles + // You can't swap items if they were knocked off in regular battles if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_RECORDED_LINK)) && (gWishFutureKnock.knockedOffMons[sideAttacker] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] - || gWishFutureKnock.knockedOffMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]] - || gWishFutureKnock.meltedItemMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] - || gWishFutureKnock.meltedItemMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]])) + || gWishFutureKnock.knockedOffMons[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]])) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } From ff60882b29de2aa1a7d390adc3d1cc2f8bb21010 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Tue, 23 Nov 2021 11:04:39 +1300 Subject: [PATCH 20/29] Requested changes --- include/constants/battle_move_effects.h | 2 +- include/constants/battle_script_commands.h | 5 ++--- include/constants/battle_string_ids.h | 8 +++----- src/battle_message.c | 4 ---- src/battle_script_commands.c | 19 ++++++++++--------- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index c6afed12c..9baabde5c 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -393,6 +393,6 @@ #define EFFECT_BEAK_BLAST 387 #define EFFECT_COURT_CHANGE 388 -#define NUM_BATTLE_MOVE_EFFECTS 390 +#define NUM_BATTLE_MOVE_EFFECTS 389 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 897bf35fb..96796ea2d 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -208,9 +208,8 @@ #define VARIOUS_SET_OCTOLOCK 135 #define VARIOUS_CUT_1_3_HP_RAISE_STATS 136 #define VARIOUS_TRY_END_NEUTRALIZING_GAS 137 -#define VARIOUS_TRY_SET_CORROSIVE_GAS 138 -#define VARIOUS_SET_BEAK_BLAST 139 -#define VARIOUS_SWAP_SIDE_STATUSES 140 +#define VARIOUS_SET_BEAK_BLAST 138 +#define VARIOUS_SWAP_SIDE_STATUSES 139 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index ee4b25115..ccbc5a536 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -611,12 +611,10 @@ #define STRINGID_NEUTRALIZINGGASOVER 608 #define STRINGID_PKMNINSNAPTRAP 609 #define STRINGID_METEORBEAMCHARGING 610 -#define STRINGID_ITEMMELTED 611 -#define STRINGID_HEATUPBEAK 612 -#define STRINGID_COURTCHANGE 613 -#define STRINGID_PREPARESHELLTRAP 614 +#define STRINGID_HEATUPBEAK 611 +#define STRINGID_COURTCHANGE 612 -#define BATTLESTRINGS_COUNT 615 +#define BATTLESTRINGS_COUNT 613 // 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 18364849a..4ac9ef9b4 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -737,17 +737,13 @@ static const u8 sText_CantEscapeBecauseOfCurrentMove[] = _("{B_DEF_NAME_WITH_PRE static const u8 sText_NeutralizingGasEnters[] = _("Neutralizing Gas filled the area!"); static const u8 sText_NeutralizingGasOver[] = _("The effects of Neutralizing\nGas wore off!"); 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!"); -static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set\n a shell trap!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { - [STRINGID_PREPARESHELLTRAP - 12] = sText_PrepareShellTrap, [STRINGID_COURTCHANGE - 12] = sText_CourtChange, [STRINGID_HEATUPBEAK - 12] = sText_HeatingUpBeak, - [STRINGID_ITEMMELTED - 12] = sText_PkmnItemMelted, [STRINGID_METEORBEAMCHARGING - 12] = sText_MeteorBeamCharging, [STRINGID_PKMNINSNAPTRAP - 12] = sText_PkmnInSnapTrap, [STRINGID_NEUTRALIZINGGASOVER - 12] = sText_NeutralizingGasOver, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8e2c59d8a..21150f833 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7525,15 +7525,15 @@ static bool32 IsRototillerAffected(u32 battlerId) #define COURTCHANGE_SWAP(status, structField, temp) \ { \ - temp = gSideStatuses[0]; \ - if (gSideStatuses[1] & status) \ - gSideStatuses[0] |= status; \ + temp = gSideStatuses[B_SIDE_PLAYER]; \ + if (gSideStatuses[B_SIDE_OPPONENT] & status) \ + gSideStatuses[B_SIDE_PLAYER] |= status; \ else \ - gSideStatuses[0] &= ~(status); \ + gSideStatuses[B_SIDE_PLAYER] &= ~(status); \ if (temp & status) \ - gSideStatuses[1] |= status; \ + gSideStatuses[B_SIDE_OPPONENT] |= status; \ else \ - gSideStatuses[1] &= ~(status); \ + gSideStatuses[B_SIDE_OPPONENT] &= ~(status); \ SWAP(sideTimer0->structField, sideTimer1->structField, temp);\ } \ @@ -7545,8 +7545,8 @@ static bool32 IsRototillerAffected(u32 battlerId) static bool32 CourtChangeSwapSideStatuses(void) { - struct SideTimer *sideTimer0 = &gSideTimers[0]; - struct SideTimer *sideTimer1 = &gSideTimers[1]; + struct SideTimer *sideTimer0 = &gSideTimers[B_SIDE_PLAYER]; + struct SideTimer *sideTimer1 = &gSideTimers[B_SIDE_OPPONENT]; u32 temp; // TODO: add Pledge-related effects @@ -11290,7 +11290,8 @@ static bool8 IsTwoTurnsMove(u16 move) || gBattleMoves[move].effect == EFFECT_TWO_TURNS_ATTACK || gBattleMoves[move].effect == EFFECT_SOLARBEAM || gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE - || gBattleMoves[move].effect == EFFECT_BIDE) + || gBattleMoves[move].effect == EFFECT_BIDE + || gBattleMoves[move].effect == EFFECT_METEOR_BEAM) return TRUE; else return FALSE; From 6b8f86c276ee87bf6246bcfc2149fcffcb233833 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Tue, 23 Nov 2021 11:05:36 +1300 Subject: [PATCH 21/29] Snap Trap placeholder anims Set up animation data for Snap Trap so it can be easily replaced with a proper animation later. --- data/battle_anim_scripts.s | 8 ++++++-- include/constants/battle_anim.h | 1 + src/battle_anim_throw.c | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 8dbdcea73..bc3821563 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13601,8 +13601,8 @@ Move_DRUM_BEATING:: blendoff end -Move_SNAP_TRAP:: - end @ to do: +Move_SNAP_TRAP:: @ placeholder + goto Move_BITE Move_PYRO_BALL:: loadspritegfx ANIM_TAG_FLAT_ROCK @@ -24209,6 +24209,7 @@ General_TurnTrap: jumpargeq 0, TRAP_ANIM_SAND_TOMB, Status_SandTomb jumpargeq 0, TRAP_ANIM_MAGMA_STORM, Status_MagmaStorm jumpargeq 0, TRAP_ANIM_INFESTATION, Status_Infestation + jumpargeq 0, TRAP_ANIM_SNAP_TRAP, Status_Snap_Trap goto Status_BindWrap Status_BindWrap: loadspritegfx ANIM_TAG_TENDRILS @@ -24295,6 +24296,9 @@ Status_Clamp: waitforvisualfinish end +Status_Snap_Trap: @ placeholder + goto Move_BITE + Status_SandTomb: loadspritegfx ANIM_TAG_MUD_SAND createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, 4, 2, 0, 7, RGB(19, 17, 0) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 8b0e81264..d11bc797c 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -569,6 +569,7 @@ #define TRAP_ANIM_SAND_TOMB 4 #define TRAP_ANIM_MAGMA_STORM 5 #define TRAP_ANIM_INFESTATION 6 +#define TRAP_ANIM_SNAP_TRAP 7 // Weather defines for battle animation scripts. #define ANIM_WEATHER_NONE 0 diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index f325cba07..4413a4674 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -2500,6 +2500,8 @@ void AnimTask_GetTrappedMoveAnimId(u8 taskId) gBattleAnimArgs[0] = TRAP_ANIM_MAGMA_STORM; else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_INFESTATION) gBattleAnimArgs[0] = TRAP_ANIM_INFESTATION; + else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SNAP_TRAP) + gBattleAnimArgs[0] = TRAP_ANIM_SNAP_TRAP; else gBattleAnimArgs[0] = TRAP_ANIM_BIND; From fa0b5188bb1ecbc31ad2e604dc1a8adc488abcb7 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Tue, 23 Nov 2021 16:56:11 +1300 Subject: [PATCH 22/29] Dynamic move targeting Properly implement Expanding Force by replacing all instances that read move target from gBattleMoves with a function. --- include/battle_util.h | 2 +- src/battle_ai_main.c | 24 ++++++------- src/battle_ai_util.c | 3 +- src/battle_anim.c | 2 +- src/battle_controller_opponent.c | 6 ++-- src/battle_controller_player.c | 18 ++++------ src/battle_controller_player_partner.c | 4 +-- src/battle_gfx_sfx_util.c | 18 +++++----- src/battle_script_commands.c | 33 +++++++++-------- src/battle_util.c | 50 ++++++++++++++++---------- src/contest.c | 2 +- 11 files changed, 87 insertions(+), 75 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index b1a2a1534..47bc2cc56 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -163,7 +163,7 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); void TryToApplyMimicry(u8 battlerId, bool8 various); void TryToRevertMimicry(void); void RestoreBattlerOriginalTypes(u8 battlerId); - +u32 GetMoveTargetType(u8 battlerId, u16 move); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index e3b8e8d5d..dda1ff9cc 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -521,7 +521,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) u8 atkPriority = GetMovePriority(battlerAtk, move); u16 moveEffect = gBattleMoves[move].effect; s32 moveType; - u16 moveTarget = gBattleMoves[move].target; + u16 moveTarget = GetMoveTargetType(battlerAtk, move); u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move); u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef); bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); @@ -537,7 +537,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) GET_MOVE_TYPE(move, moveType); // check non-user target - if (!(gBattleMoves[move].target & MOVE_TARGET_USER)) + if (moveTarget & MOVE_TARGET_USER) { // handle negative checks on non-user target // check powder moves @@ -2336,7 +2336,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } else { - if (gBattleMoves[instructedMove].target & (MOVE_TARGET_SELECTED + if (GetMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_DEPENDS | MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH @@ -2533,7 +2533,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) // move data u8 moveType = gBattleMoves[move].type; u16 effect = gBattleMoves[move].effect; - u16 target = gBattleMoves[move].target; + u16 moveTarget = GetMoveTargetType(battlerAtk, move); // ally data u8 battlerAtkPartner = AI_DATA->battlerAtkPartner; u16 atkPartnerAbility = AI_DATA->atkPartnerAbility; @@ -2572,7 +2572,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (IsAttackBoostMoveEffect(effect)) score -= 3; // encourage moves hitting multiple opponents - if (!IS_MOVE_STATUS(move) && (gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + if (!IS_MOVE_STATUS(move) && (moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) score += 3; } } @@ -2640,7 +2640,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (GetMoveDamageResult(move) == MOVE_POWER_OTHER) { // partner ability checks - if (!partnerProtecting && gBattleMoves[move].target != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move)) + if (!partnerProtecting && moveTarget != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move)) { switch (atkPartnerAbility) { @@ -2840,7 +2840,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (instructedMove != MOVE_NONE && !IS_MOVE_STATUS(instructedMove) - && gBattleMoves[instructedMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) //Use instruct on multi-target moves + && (GetMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves { RETURN_SCORE_PLUS(1); } @@ -3631,24 +3631,24 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_WIDE_GUARD: - if (predictedMove != MOVE_NONE && gBattleMoves[predictedMove].target & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)) + if (predictedMove != MOVE_NONE && GetMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)) { ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); } - else if (isDoubleBattle && gBattleMoves[AI_DATA->partnerMove].target & MOVE_TARGET_FOES_AND_ALLY) + else if (isDoubleBattle && GetMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) { if (AI_DATA->atkAbility != ABILITY_TELEPATHY) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); } break; case MOVE_CRAFTY_SHIELD: - if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(gBattleMoves[predictedMove].target & MOVE_TARGET_USER)) + if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(GetMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_MAT_BLOCK: if (gDisableStructs[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE - && !IS_MOVE_STATUS(predictedMove) && !(gBattleMoves[predictedMove].target & MOVE_TARGET_USER)) + && !IS_MOVE_STATUS(predictedMove) && !(GetMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_KINGS_SHIELD: @@ -4093,7 +4093,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 10; break; case EFFECT_MAGIC_COAT: - if (IS_MOVE_STATUS(predictedMove) && gBattleMoves[predictedMove].target & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) + if (IS_MOVE_STATUS(predictedMove) && GetMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) score += 3; break; case EFFECT_RECYCLE: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 47561c765..ef6b0679f 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1919,9 +1919,8 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32 if (ignoreStatus && IS_MOVE_STATUS(moves[i])) continue; else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0) - || gBattleMoves[moves[i]].target & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) + || GetMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) continue; - if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck) return TRUE; } diff --git a/src/battle_anim.c b/src/battle_anim.c index e6152a7cf..d6761eae6 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -2195,7 +2195,7 @@ void DoMoveAnim(u16 move) gBattleAnimAttacker = gBattlerAttacker; gBattleAnimTarget = gBattlerTarget; // Make sure the anim target of moves hitting everyone is at the opposite side. - if (gBattleMoves[move].target & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle()) + if (GetMoveTargetType(gBattlerAttacker, move) & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle()) { while (GET_BATTLER_SIDE(gBattleAnimAttacker) == GET_BATTLER_SIDE(gBattleAnimTarget)) { diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index b43e80225..ff253730f 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1586,9 +1586,9 @@ static void OpponentHandleChooseMove(void) BtlController_EmitTwoReturnValues(1, 15, gBattlerTarget); break; default: - if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) gBattlerTarget = gActiveBattler; - if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) + if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & MOVE_TARGET_BOTH) { gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) @@ -1611,7 +1611,7 @@ static void OpponentHandleChooseMove(void) move = moveInfo->moves[chosenMoveId]; } while (move == MOVE_NONE); - if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + if (GetMoveTargetType(gActiveBattler, move) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gActiveBattler << 8)); else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8)); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index a970c38b7..05ad19170 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -360,6 +360,7 @@ static void HandleInputChooseTarget(void) s32 i; static const u8 identities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT}; u16 move = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler]); + u16 moveTarget = GetMoveTargetType(gActiveBattler, move); DoBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX, 15, 1); for (i = 0; i < gBattlersCount; i++) @@ -400,7 +401,7 @@ static void HandleInputChooseTarget(void) PlaySE(SE_SELECT); gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_HideAsMoveTarget; - if (gBattleMoves[move].target == (MOVE_TARGET_USER | MOVE_TARGET_ALLY)) + if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY)) { gMultiUsePlayerCursor ^= BIT_FLANK; } @@ -429,7 +430,7 @@ static void HandleInputChooseTarget(void) case B_POSITION_PLAYER_RIGHT: if (gActiveBattler != gMultiUsePlayerCursor) i++; - else if (gBattleMoves[move].target & MOVE_TARGET_USER_OR_SELECTED) + else if (moveTarget & MOVE_TARGET_USER_OR_SELECTED) i++; break; case B_POSITION_OPPONENT_LEFT: @@ -449,7 +450,7 @@ static void HandleInputChooseTarget(void) PlaySE(SE_SELECT); gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_HideAsMoveTarget; - if (gBattleMoves[move].target == (MOVE_TARGET_USER | MOVE_TARGET_ALLY)) + if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY)) { gMultiUsePlayerCursor ^= BIT_FLANK; } @@ -478,7 +479,7 @@ static void HandleInputChooseTarget(void) case B_POSITION_PLAYER_RIGHT: if (gActiveBattler != gMultiUsePlayerCursor) i++; - else if (gBattleMoves[move].target & MOVE_TARGET_USER_OR_SELECTED) + else if (moveTarget & MOVE_TARGET_USER_OR_SELECTED) i++; break; case B_POSITION_OPPONENT_LEFT: @@ -609,16 +610,9 @@ static void HandleInputChooseMove(void) else moveTarget = MOVE_TARGET_SELECTED; } - else if (moveInfo->moves[gMoveSelectionCursor[gActiveBattler]] == MOVE_EXPANDING_FORCE) - { - if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN)) - moveTarget = MOVE_TARGET_BOTH; - else - moveTarget = MOVE_TARGET_SELECTED; - } else { - moveTarget = gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].target; + moveTarget = GetMoveTargetType(gActiveBattler, moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]); } if (moveTarget & MOVE_TARGET_USER) diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index f0540e65f..a72f1029b 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -1526,9 +1526,9 @@ static void PlayerPartnerHandleChooseMove(void) BattleAI_SetupAIData(0xF); chosenMoveId = BattleAI_ChooseMoveOrAction(); - if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) + if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) gBattlerTarget = gActiveBattler; - if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) + if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & MOVE_TARGET_BOTH) { gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 482a135c5..11e41ebd4 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -38,7 +38,7 @@ extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow; extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow; // this file's functions -static u8 GetBattlePalaceMoveGroup(u16 move); +static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move); static u16 GetBattlePalaceTarget(void); static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite); static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId); @@ -155,7 +155,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) { if (moveInfo->moves[i] == MOVE_NONE) break; - if (selectedGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]) && moveInfo->currentPp[i] != 0) + if (selectedGroup == GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) && moveInfo->currentPp[i] != 0) selectedMoves |= gBitTable[i]; } @@ -181,11 +181,11 @@ u16 ChooseMoveAndTargetInBattlePalace(void) { // validMoveFlags is used here as a bitfield for which moves can be used for each move group type // first 4 bits are for attack (1 for each move), then 4 bits for defense, and 4 for support - if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits)) + if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits)) validMoveFlags += (1 << 0); - if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits)) + if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits)) validMoveFlags += (1 << 4); - if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits)) + if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits)) validMoveFlags += (1 << 8); } @@ -222,7 +222,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) do { i = Random() % MAX_MON_MOVES; - if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i])) + if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i])) chosenMoveId = i; } while (chosenMoveId == -1); } @@ -251,7 +251,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) } else { - moveTarget = gBattleMoves[moveInfo->moves[chosenMoveId]].target; + moveTarget = GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]); } if (moveTarget & MOVE_TARGET_USER) @@ -273,9 +273,9 @@ u16 ChooseMoveAndTargetInBattlePalace(void) #undef numValidMoveGroups #undef validMoveGroup -static u8 GetBattlePalaceMoveGroup(u16 move) +static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move) { - switch (gBattleMoves[move].target) + switch (GetMoveTargetType(battlerId, move)) { case MOVE_TARGET_SELECTED: case MOVE_TARGET_USER_OR_SELECTED: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 21150f833..437733f1e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1313,12 +1313,12 @@ static const u8 sBattlePalaceNatureToFlavorTextId[NUM_NATURES] = [NATURE_QUIRKY] = B_MSG_EAGER_FOR_MORE, }; -static bool32 NoTargetPresent(u32 move) +static bool32 NoTargetPresent(u8 battlerId, u32 move) { if (!IsBattlerAlive(gBattlerTarget)) gBattlerTarget = GetMoveTarget(move, 0); - switch (gBattleMoves[move].target) + switch (GetMoveTargetType(battlerId, move)) { case MOVE_TARGET_SELECTED: case MOVE_TARGET_DEPENDS: @@ -1459,7 +1459,7 @@ static void Cmd_attackcanceler(void) } gHitMarker |= HITMARKER_OBEYS; - if (NoTargetPresent(gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))) + if (NoTargetPresent(gBattlerAttacker, gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))) { gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce; if (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) @@ -1741,6 +1741,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move) static void Cmd_accuracycheck(void) { u16 type, move = T2_READ_16(gBattlescriptCurrInstr + 5); + u16 moveTarget = GetMoveTargetType(gBattlerAttacker, move); if (move == ACC_CURR_MOVE) move = gCurrentMove; @@ -1770,7 +1771,7 @@ static void Cmd_accuracycheck(void) gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && - (gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY)) + (moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK; else gBattleCommunication[MISS_TYPE] = B_MSG_MISSED; @@ -1804,7 +1805,7 @@ static void Cmd_ppreduce(void) if (!gSpecialStatuses[gBattlerAttacker].ppNotAffectedByPressure) { - switch (gBattleMoves[gCurrentMove].target) + switch (GetMoveTargetType(gBattlerAttacker, gCurrentMove)) { case MOVE_TARGET_FOES_AND_ALLY: for (i = 0; i < gBattlersCount; i++) @@ -2103,6 +2104,8 @@ static void Cmd_multihitresultmessage(void) static void Cmd_attackanimation(void) { + u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove); + if (gBattleControllerExecFlags) return; @@ -2119,9 +2122,9 @@ static void Cmd_attackanimation(void) } else { - if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH - || gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY - || gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS) + if ((moveTarget & MOVE_TARGET_BOTH + || moveTarget & MOVE_TARGET_FOES_AND_ALLY + || moveTarget & MOVE_TARGET_DEPENDS) && gBattleScripting.animTargetsHit) { gBattlescriptCurrInstr++; @@ -5237,6 +5240,8 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon. + { + u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove); // Set a flag if move hits either target (for throat spray that can't check damage) if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) @@ -5245,14 +5250,13 @@ static void Cmd_moveend(void) if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !gProtectStructs[gBattlerAttacker].chargingTurn - && (gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH - || gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY - || (gBattleMoves[gCurrentMove].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN))) + && (moveTarget == MOVE_TARGET_BOTH + || moveTarget == MOVE_TARGET_FOES_AND_ALLY) && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) { u8 battlerId; - if (gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY) + if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { gHitMarker |= HITMARKER_NO_PPDEDUCT; for (battlerId = gBattlerTarget + 1; battlerId < gBattlersCount; battlerId++) @@ -5288,6 +5292,7 @@ static void Cmd_moveend(void) RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove); gBattleScripting.moveendState++; break; + } case MOVEEND_EJECT_BUTTON: if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW @@ -9506,7 +9511,7 @@ static void Cmd_jumpifnexttargetvalid(void) for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++) { - if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER)) + if (gBattlerTarget == gBattlerAttacker && !(GetMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) continue; if (IsBattlerAlive(gBattlerTarget)) break; @@ -12000,7 +12005,7 @@ static void Cmd_selectfirstvalidtarget(void) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { - if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER)) + if (gBattlerTarget == gBattlerAttacker && !(GetMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) continue; if (IsBattlerAlive(gBattlerTarget)) break; diff --git a/src/battle_util.c b/src/battle_util.c index e946fe8f0..dcde7b8ce 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -237,6 +237,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) void HandleAction_UseMove(void) { u32 i, side, moveType, var = 4; + u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove); gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; if (gBattleStruct->field_91 & gBitTable[gBattlerAttacker] || !IsBattlerAlive(gBattlerAttacker)) @@ -309,14 +310,14 @@ void HandleAction_UseMove(void) // choose target side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove) - && gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED + && moveTarget == MOVE_TARGET_SELECTED && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget)) { gBattlerTarget = gSideTimers[side].followmeTarget; } else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gSideTimers[side].followmeTimer == 0 - && (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER) + && (gBattleMoves[gCurrentMove].power != 0 || moveTarget != MOVE_TARGET_USER) && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) || (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { @@ -337,7 +338,7 @@ void HandleAction_UseMove(void) } if (var == 4) { - if (gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM) + if (moveTarget & MOVE_TARGET_RANDOM) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) { @@ -354,7 +355,7 @@ void HandleAction_UseMove(void) gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); } } - else if (gBattleMoves[gChosenMove].target & MOVE_TARGET_FOES_AND_ALLY) + else if (moveTarget & MOVE_TARGET_FOES_AND_ALLY) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { @@ -395,7 +396,7 @@ void HandleAction_UseMove(void) } } else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM) + && moveTarget & MOVE_TARGET_RANDOM) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) { @@ -418,7 +419,7 @@ void HandleAction_UseMove(void) gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK); } } - else if (gBattleMoves[gChosenMove].target == MOVE_TARGET_ALLY) + else if (moveTarget == MOVE_TARGET_ALLY) { if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker))) gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker); @@ -426,7 +427,7 @@ void HandleAction_UseMove(void) gBattlerTarget = gBattlerAttacker; } else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && gBattleMoves[gChosenMove].target == MOVE_TARGET_FOES_AND_ALLY) + && moveTarget == MOVE_TARGET_FOES_AND_ALLY) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { @@ -4668,7 +4669,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITYEFFECT_MOVES_BLOCK: // 2 - if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(gBattleMoves[move].target & MOVE_TARGET_USER)) + { + u16 moveTarget = GetMoveTargetType(battler, move); + + if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(moveTarget & MOVE_TARGET_USER)) || (gLastUsedAbility == ABILITY_BULLETPROOF && gBattleMoves[move].flags & FLAG_BALLISTIC)) { if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) @@ -4691,14 +4695,14 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move else if (BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) && !(IS_MOVE_STATUS(move) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE)) { - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected gBattleScripting.battler = gBattlerAbility = gBattlerTarget; gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; effect = 1; } - break; + } case ABILITYEFFECT_ABSORBING: // 3 if (move != MOVE_NONE) { @@ -7257,15 +7261,12 @@ u32 GetMoveTarget(u16 move, u8 setTarget) if (setTarget) moveTarget = setTarget - 1; else - moveTarget = gBattleMoves[move].target; - + moveTarget = GetMoveTargetType(gBattlerAttacker, move); + // Special cases if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) moveTarget = MOVE_TARGET_USER; - if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN)) - moveTarget = MOVE_TARGET_BOTH; - switch (moveTarget) { case MOVE_TARGET_SELECTED: @@ -7528,7 +7529,7 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) else if (gProtectStructs[battlerId].protected) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD - && gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + && GetMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; else if (gProtectStructs[battlerId].banefulBunkered) return TRUE; @@ -7654,7 +7655,7 @@ u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc) u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef) { - switch (gBattleMoves[move].target) + switch (GetMoveTargetType(gBattlerAttacker, move)) { case MOVE_TARGET_BOTH: return IsBattlerAlive(battlerDef) @@ -9818,7 +9819,7 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 chec return FALSE; if (GetBattlerSide(battlerPrankster) == GetBattlerSide(battlerDef)) return FALSE; - if (checkTarget && (gBattleMoves[move].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS))) + if (checkTarget && (GetMoveTargetType(battlerPrankster, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS))) return FALSE; if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)) return FALSE; @@ -9850,3 +9851,16 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags) } return FALSE; } + +// Gets move target before redirection effects etc. are applied +// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED +u32 GetMoveTargetType(u8 battlerId, u16 move) +{ + u32 target; + + if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE + && IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN)) + return MOVE_TARGET_BOTH; + else + return gBattleMoves[move].target; +} diff --git a/src/contest.c b/src/contest.c index 46fa0efed..c876f02cc 100644 --- a/src/contest.c +++ b/src/contest.c @@ -5388,7 +5388,7 @@ static void SetBattleTargetSpritePosition(void) static void SetMoveTargetPosition(u16 move) { - switch (gBattleMoves[move].target) + switch (GetMoveTargetType(gBattlerAttacker, move)) { case MOVE_TARGET_USER_OR_SELECTED: case MOVE_TARGET_USER: From a89ce0c38abf74470a78091152c8f5900cdde792 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Tue, 23 Nov 2021 22:54:30 +1300 Subject: [PATCH 23/29] Swapped webs don't trigger Defiant Track the side that originally set Sticky Web, and if it matches the side the target of the speed drop is on, don't activate Defiant. Hard to tell if this is a bug or a feature in gen 8 - maybe the swapped webs are considered a "friendly" effect? Also, fix Sticky Web not activating Defiant. --- data/battle_scripts_1.s | 1 + include/battle.h | 2 ++ include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 39 ++++++++++++---------- src/battle_util.c | 5 ++- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index eeeba7cf7..dabdf1383 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6712,6 +6712,7 @@ BattleScript_ToxicSpikesPoisoned:: BattleScript_StickyWebOnSwitchIn:: savetarget copybyte gBattlerTarget, sBATTLER + setbyte sSTICKY_WEB_STAT_DROP, 1 printstring STRINGID_STICKYWEBSWITCHIN waitmessage B_WAIT_TIME_LONG jumpifability BS_TARGET, ABILITY_MIRROR_ARMOR, BattleScript_MirrorArmorReflectStickyWeb diff --git a/include/battle.h b/include/battle.h index f534f416b..7ccb492a6 100644 --- a/include/battle.h +++ b/include/battle.h @@ -211,6 +211,7 @@ struct SideTimer u8 toxicSpikesAmount; u8 stealthRockAmount; u8 stickyWebAmount; + u8 stickyWebBattlerSide; // Used for Court Change u8 auroraVeilTimer; u8 auroraVeilBattlerId; u8 tailwindTimer; @@ -704,6 +705,7 @@ struct BattleScripting u16 abilityPopupOverwrite; u8 switchCase; // Special switching conditions, eg. red card u8 overrideBerryRequirements; + u8 stickyWebStatDrop; // To prevent Defiant activating on a Court Change'd Sticky Web }; // rom_80A5C6C diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 96796ea2d..331794816 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -39,6 +39,7 @@ #define sABILITY_OVERWRITE gBattleScripting + 0x34 #define sSWITCH_CASE gBattleScripting + 0x36 #define sBERRY_OVERRIDE gBattleScripting + 0x37 +#define sSTICKY_WEB_STAT_DROP gBattleScripting + 0x38 #define cMULTISTRING_CHOOSER gBattleCommunication + 5 #define cMISS_TYPE gBattleCommunication + 6 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index db3a030ae..672aa92a1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7536,30 +7536,30 @@ static bool32 IsRototillerAffected(u32 battlerId) return TRUE; } -#define COURTCHANGE_SWAP(status, structField, temp) \ -{ \ - temp = gSideStatuses[B_SIDE_PLAYER]; \ - if (gSideStatuses[B_SIDE_OPPONENT] & status) \ - gSideStatuses[B_SIDE_PLAYER] |= status; \ - else \ - gSideStatuses[B_SIDE_PLAYER] &= ~(status); \ - if (temp & status) \ - gSideStatuses[B_SIDE_OPPONENT] |= status; \ - else \ - gSideStatuses[B_SIDE_OPPONENT] &= ~(status); \ - SWAP(sideTimer0->structField, sideTimer1->structField, temp);\ -} \ +#define COURTCHANGE_SWAP(status, structField, temp) \ +{ \ + temp = gSideStatuses[B_SIDE_PLAYER]; \ + if (gSideStatuses[B_SIDE_OPPONENT] & status) \ + gSideStatuses[B_SIDE_PLAYER] |= status; \ + else \ + gSideStatuses[B_SIDE_PLAYER] &= ~(status); \ + if (temp & status) \ + gSideStatuses[B_SIDE_OPPONENT] |= status; \ + else \ + gSideStatuses[B_SIDE_OPPONENT] &= ~(status); \ + SWAP(sideTimerPlayer->structField, sideTimerOpp->structField, temp);\ +} \ #define UPDATE_COURTCHANGED_BATTLER(structField)\ { \ - sideTimer0->structField ^= BIT_SIDE; \ - sideTimer1->structField ^= BIT_SIDE; \ + sideTimerPlayer->structField ^= BIT_SIDE; \ + sideTimerOpp->structField ^= BIT_SIDE; \ } \ static bool32 CourtChangeSwapSideStatuses(void) { - struct SideTimer *sideTimer0 = &gSideTimers[B_SIDE_PLAYER]; - struct SideTimer *sideTimer1 = &gSideTimers[B_SIDE_OPPONENT]; + struct SideTimer *sideTimerPlayer = &gSideTimers[B_SIDE_PLAYER]; + struct SideTimer *sideTimerOpp = &gSideTimers[B_SIDE_OPPONENT]; u32 temp; // TODO: add Pledge-related effects @@ -7588,6 +7588,9 @@ static bool32 CourtChangeSwapSideStatuses(void) UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId); UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId); UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId); + + // Track which side originally set the Sticky Web + SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp); } static void Cmd_various(void) @@ -11996,6 +11999,7 @@ static void Cmd_recoverbasedonsunlight(void) static void Cmd_setstickyweb(void) { u8 targetSide = GetBattlerSide(gBattlerTarget); + if (gSideStatuses[targetSide] & SIDE_STATUS_STICKY_WEB) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); @@ -12003,6 +12007,7 @@ static void Cmd_setstickyweb(void) else { gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB; + gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side gSideTimers[targetSide].stickyWebAmount = 1; gBattleStruct->stickyWebUser = gBattlerAttacker; // For Mirror Armor gBattlescriptCurrInstr += 5; diff --git a/src/battle_util.c b/src/battle_util.c index 0ddff3483..7aba05fc1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1453,6 +1453,7 @@ bool8 WasUnableToUseMove(u8 battler) void PrepareStringBattle(u16 stringId, u8 battler) { + u32 targetSide = GetBattlerSide(gBattlerTarget); // Support for Contrary ability. // If a move attempted to raise stat - print "won't increase". // If a move attempted to lower stat - print "won't decrease". @@ -1471,8 +1472,10 @@ void PrepareStringBattle(u16 stringId, u8 battler) && ((GetBattlerAbility(gBattlerTarget) == ABILITY_DEFIANT && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) || (GetBattlerAbility(gBattlerTarget) == ABILITY_COMPETITIVE && CompareStat(gBattlerTarget, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))) && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != BATTLE_PARTNER(gBattlerTarget) - && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) + // && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) // Why was this here? Needs investigating + && !(gBattleScripting.stickyWebStatDrop == 1 && gSideTimers[targetSide].stickyWebBattlerSide == targetSide)) // Sticky Web must have been set by the foe { + gBattleScripting.stickyWebStatDrop = 0; gBattlerAbility = gBattlerTarget; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_DefiantActivates; From fd4414fe627eb4efcb42362d18fe68872d27b478 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Tue, 23 Nov 2021 23:01:43 +1300 Subject: [PATCH 24/29] Spaces instead of tabs --- data/battle_anim_scripts.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index bc3821563..be8dfb9a4 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -827,8 +827,8 @@ gBattleAnims_General:: .4byte General_GulpMissile @ B_ANIM_GULP_MISSILE .4byte General_StrongWinds @ B_ANIM_STRONG_WINDS .4byte General_PrimalReversion @ B_ANIM_PRIMAL_REVERSION - .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP - .4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP + .4byte General_BeakBlastSetUp @ B_ANIM_BEAK_BLAST_SETUP + .4byte General_ShellTrapSetUp @ B_ANIM_SHELL_TRAP_SETUP .align 2 gBattleAnims_Special:: From cca7ec8c58d0becd96fb9ea6cd067d676ffafcd6 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 24 Nov 2021 12:09:54 +1300 Subject: [PATCH 25/29] Fix and rename GetMoveTargetType Change name to GetBattlerMoveTargetType and make it actually use the battlerId argument. --- include/battle_util.h | 2 +- src/battle_ai_main.c | 18 +++++++++--------- src/battle_ai_util.c | 2 +- src/battle_anim.c | 2 +- src/battle_controller_opponent.c | 6 +++--- src/battle_controller_player.c | 4 ++-- src/battle_gfx_sfx_util.c | 4 ++-- src/battle_script_commands.c | 14 +++++++------- src/battle_util.c | 16 ++++++++-------- src/contest.c | 2 +- 10 files changed, 35 insertions(+), 35 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 47bc2cc56..35eea7da1 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -163,7 +163,7 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); void TryToApplyMimicry(u8 battlerId, bool8 various); void TryToRevertMimicry(void); void RestoreBattlerOriginalTypes(u8 battlerId); -u32 GetMoveTargetType(u8 battlerId, u16 move); +u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 3b6716485..25265b973 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -484,7 +484,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) u8 atkPriority = GetMovePriority(battlerAtk, move); u16 moveEffect = gBattleMoves[move].effect; s32 moveType; - u16 moveTarget = GetMoveTargetType(battlerAtk, move); + u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move); u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef); bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); @@ -2299,7 +2299,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } else { - if (GetMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED + if (GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_DEPENDS | MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH @@ -2496,7 +2496,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) // move data u8 moveType = gBattleMoves[move].type; u16 effect = gBattleMoves[move].effect; - u16 moveTarget = GetMoveTargetType(battlerAtk, move); + u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); // ally data u8 battlerAtkPartner = AI_DATA->battlerAtkPartner; u16 atkPartnerAbility = AI_DATA->atkPartnerAbility; @@ -2803,7 +2803,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (instructedMove != MOVE_NONE && !IS_MOVE_STATUS(instructedMove) - && (GetMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves + && (GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves { RETURN_SCORE_PLUS(1); } @@ -3603,24 +3603,24 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_WIDE_GUARD: - if (predictedMove != MOVE_NONE && GetMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)) + if (predictedMove != MOVE_NONE && GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)) { ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); } - else if (isDoubleBattle && GetMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) + else if (isDoubleBattle && GetBattlerMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) { if (AI_DATA->atkAbility != ABILITY_TELEPATHY) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); } break; case MOVE_CRAFTY_SHIELD: - if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(GetMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) + if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_MAT_BLOCK: if (gDisableStructs[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE - && !IS_MOVE_STATUS(predictedMove) && !(GetMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) + && !IS_MOVE_STATUS(predictedMove) && !(GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_KINGS_SHIELD: @@ -4065,7 +4065,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 10; break; case EFFECT_MAGIC_COAT: - if (IS_MOVE_STATUS(predictedMove) && GetMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) + if (IS_MOVE_STATUS(predictedMove) && GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) score += 3; break; case EFFECT_RECYCLE: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 664078e55..7f30862d1 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1921,7 +1921,7 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32 if (ignoreStatus && IS_MOVE_STATUS(moves[i])) continue; else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0) - || GetMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) + || GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) continue; if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck) return TRUE; diff --git a/src/battle_anim.c b/src/battle_anim.c index d6761eae6..fba5cbcd8 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -2195,7 +2195,7 @@ void DoMoveAnim(u16 move) gBattleAnimAttacker = gBattlerAttacker; gBattleAnimTarget = gBattlerTarget; // Make sure the anim target of moves hitting everyone is at the opposite side. - if (GetMoveTargetType(gBattlerAttacker, move) & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle()) + if (GetBattlerMoveTargetType(gBattlerAttacker, move) & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle()) { while (GET_BATTLER_SIDE(gBattleAnimAttacker) == GET_BATTLER_SIDE(gBattleAnimTarget)) { diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 4482c175d..448c9b480 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1574,9 +1574,9 @@ static void OpponentHandleChooseAction(void) BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0); break; default: - if (GetMoveTargetType(gActiveBattler, moveInfo.moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + if (GetBattlerMoveTargetType(gActiveBattler, moveInfo.moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) gBattlerTarget = gActiveBattler; - if (GetMoveTargetType(gActiveBattler, moveInfo.moves[chosenMoveId]) & MOVE_TARGET_BOTH) + if (GetBattlerMoveTargetType(gActiveBattler, moveInfo.moves[chosenMoveId]) & MOVE_TARGET_BOTH) { gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) @@ -1600,7 +1600,7 @@ static void OpponentHandleChooseAction(void) move = moveInfo.moves[chosenMoveId]; } while (move == MOVE_NONE); - if (GetMoveTargetType(gActiveBattler, move) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + if (GetBattlerMoveTargetType(gActiveBattler, move) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (gActiveBattler << 8)); else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8)); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 05ad19170..caa3b0689 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -360,7 +360,7 @@ static void HandleInputChooseTarget(void) s32 i; static const u8 identities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT}; u16 move = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler]); - u16 moveTarget = GetMoveTargetType(gActiveBattler, move); + u16 moveTarget = GetBattlerMoveTargetType(gActiveBattler, move); DoBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX, 15, 1); for (i = 0; i < gBattlersCount; i++) @@ -612,7 +612,7 @@ static void HandleInputChooseMove(void) } else { - moveTarget = GetMoveTargetType(gActiveBattler, moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]); + moveTarget = GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]); } if (moveTarget & MOVE_TARGET_USER) diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 11e41ebd4..73adc442b 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -251,7 +251,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) } else { - moveTarget = GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]); + moveTarget = GetBattlerMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]); } if (moveTarget & MOVE_TARGET_USER) @@ -275,7 +275,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move) { - switch (GetMoveTargetType(battlerId, move)) + switch (GetBattlerMoveTargetType(battlerId, move)) { case MOVE_TARGET_SELECTED: case MOVE_TARGET_USER_OR_SELECTED: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 672aa92a1..8b6b31738 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1318,7 +1318,7 @@ static bool32 NoTargetPresent(u8 battlerId, u32 move) if (!IsBattlerAlive(gBattlerTarget)) gBattlerTarget = GetMoveTarget(move, 0); - switch (GetMoveTargetType(battlerId, move)) + switch (GetBattlerMoveTargetType(battlerId, move)) { case MOVE_TARGET_SELECTED: case MOVE_TARGET_DEPENDS: @@ -1741,7 +1741,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move) static void Cmd_accuracycheck(void) { u16 type, move = T2_READ_16(gBattlescriptCurrInstr + 5); - u16 moveTarget = GetMoveTargetType(gBattlerAttacker, move); + u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move); if (move == ACC_CURR_MOVE) move = gCurrentMove; @@ -1805,7 +1805,7 @@ static void Cmd_ppreduce(void) if (!gSpecialStatuses[gBattlerAttacker].ppNotAffectedByPressure) { - switch (GetMoveTargetType(gBattlerAttacker, gCurrentMove)) + switch (GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove)) { case MOVE_TARGET_FOES_AND_ALLY: for (i = 0; i < gBattlersCount; i++) @@ -2104,7 +2104,7 @@ static void Cmd_multihitresultmessage(void) static void Cmd_attackanimation(void) { - u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove); + u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); if (gBattleControllerExecFlags) return; @@ -5241,7 +5241,7 @@ static void Cmd_moveend(void) break; case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon. { - u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove); + u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); // Set a flag if move hits either target (for throat spray that can't check damage) if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) @@ -9522,7 +9522,7 @@ static void Cmd_jumpifnexttargetvalid(void) for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++) { - if (gBattlerTarget == gBattlerAttacker && !(GetMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) + if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) continue; if (IsBattlerAlive(gBattlerTarget)) break; @@ -12018,7 +12018,7 @@ static void Cmd_selectfirstvalidtarget(void) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { - if (gBattlerTarget == gBattlerAttacker && !(GetMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) + if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) continue; if (IsBattlerAlive(gBattlerTarget)) break; diff --git a/src/battle_util.c b/src/battle_util.c index 7aba05fc1..3cb6b6d86 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -237,7 +237,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) void HandleAction_UseMove(void) { u32 i, side, moveType, var = 4; - u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove); + u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; if (gBattleStruct->field_91 & gBitTable[gBattlerAttacker] || !IsBattlerAlive(gBattlerAttacker)) @@ -4674,7 +4674,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move break; case ABILITYEFFECT_MOVES_BLOCK: // 2 { - u16 moveTarget = GetMoveTargetType(battler, move); + u16 moveTarget = GetBattlerMoveTargetType(battler, move); if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(moveTarget & MOVE_TARGET_USER)) || (gLastUsedAbility == ABILITY_BULLETPROOF && gBattleMoves[move].flags & FLAG_BALLISTIC)) @@ -7265,7 +7265,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) if (setTarget) moveTarget = setTarget - 1; else - moveTarget = GetMoveTargetType(gBattlerAttacker, move); + moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move); // Special cases if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) @@ -7538,7 +7538,7 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) else if (gProtectStructs[battlerId].protected) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD - && GetMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + && GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; else if (gProtectStructs[battlerId].banefulBunkered) return TRUE; @@ -7664,7 +7664,7 @@ u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc) u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef) { - switch (GetMoveTargetType(gBattlerAttacker, move)) + switch (GetBattlerMoveTargetType(gBattlerAttacker, move)) { case MOVE_TARGET_BOTH: return IsBattlerAlive(battlerDef) @@ -9828,7 +9828,7 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 chec return FALSE; if (GetBattlerSide(battlerPrankster) == GetBattlerSide(battlerDef)) return FALSE; - if (checkTarget && (GetMoveTargetType(battlerPrankster, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS))) + if (checkTarget && (GetBattlerMoveTargetType(battlerPrankster, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS))) return FALSE; if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)) return FALSE; @@ -9863,12 +9863,12 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags) // Gets move target before redirection effects etc. are applied // Possible return values are defined in battle.h following MOVE_TARGET_SELECTED -u32 GetMoveTargetType(u8 battlerId, u16 move) +u32 GetBattlerMoveTargetType(u8 battlerId, u16 move) { u32 target; if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE - && IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN)) + && IsBattlerTerrainAffected(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN)) return MOVE_TARGET_BOTH; else return gBattleMoves[move].target; diff --git a/src/contest.c b/src/contest.c index c876f02cc..f8e6be3ef 100644 --- a/src/contest.c +++ b/src/contest.c @@ -5388,7 +5388,7 @@ static void SetBattleTargetSpritePosition(void) static void SetMoveTargetPosition(u16 move) { - switch (GetMoveTargetType(gBattlerAttacker, move)) + switch (GetBattlerMoveTargetType(gBattlerAttacker, move)) { case MOVE_TARGET_USER_OR_SELECTED: case MOVE_TARGET_USER: From 0a27b575dc7764d976ae5bcd7bc48365cf6e1dc3 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Thu, 27 Jan 2022 17:24:11 +1300 Subject: [PATCH 26/29] Fix merge error in battle scripts --- data/battle_scripts_1.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index fec6a18d7..ebcaf38d7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -403,6 +403,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectOctolock @ EFFECT_OCTOLOCK .4byte BattleScript_EffectClangorousSoul @ EFFECT_CLANGOROUS_SOUL .4byte BattleScript_EffectHit @ EFFECT_BOLT_BEAK + .4byte BattleScript_EffectSkyDrop @ EFFECT_SKY_DROP .4byte BattleScript_EffectHit @ EFFECT_EXPANDING_FORCE .4byte BattleScript_EffectScaleShot @ EFFECT_SCALE_SHOT .4byte BattleScript_EffectMeteorBeam @ EFFECT_METEOR_BEAM @@ -512,11 +513,10 @@ BattleScript_ScaleShotPrintStrings:: BattleScript_ScaleShotEnd:: setmoveeffect MOVE_EFFECT_SCALE_SHOT | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN seteffectwithchance - tryfaintmon BS_TARGET, FALSE, NULL + tryfaintmon BS_TARGET moveendcase MOVEEND_SYNCHRONIZE_TARGET moveendfrom MOVEEND_STATUS_IMMUNITY_ABILITIES end - .4byte BattleScript_EffectSkyDrop @ EFFECT_SKY_DROP BattleScript_EffectSkyDrop: jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SkyDropTurn2 From af6242f2e027d62eb7cb34971adb142f7eb74fe9 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 27 Apr 2022 21:51:10 +1200 Subject: [PATCH 27/29] Requested changes, Sticky Web edge case Fix issues found by ghoulslash, and make sure Defiant works properly with Sticky Web and Court Change. --- data/battle_scripts_1.s | 2 +- include/constants/battle_script_commands.h | 2 +- src/battle_ai_main.c | 2 +- src/battle_script_commands.c | 8 ++++++-- src/battle_util.c | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 37eaa5b83..6574e26ab 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7290,7 +7290,7 @@ BattleScript_DefDownSpeedUpTryDef:: setstatchanger STAT_DEF, 1, TRUE statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_DefDownSpeedUpTrySpeed jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpTrySpeed - printfromtable gStatUpStringIds + printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefDownSpeedUpTrySpeed: playstatchangeanimation BS_ATTACKER, BIT_SPEED, 0 diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 2903963f4..da44714e2 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -39,7 +39,7 @@ #define sABILITY_OVERWRITE (gBattleScripting + 0x34) // abilityPopupOverwrite #define sSWITCH_CASE (gBattleScripting + 0x36) // switchCase #define sBERRY_OVERRIDE (gBattleScripting + 0x37) // overrideBerryRequirements -#define sSTICKY_WEB_STAT_DROP (gBattleScripting + 0x38) // +#define sSTICKY_WEB_STAT_DROP (gBattleScripting + 0x38) // stickyWebStatDrop // Array entries for battle communication #define MULTIUSE_STATE 0 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 02597a0aa..16e830efe 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -566,7 +566,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) GET_MOVE_TYPE(move, moveType); // check non-user target - if (moveTarget & MOVE_TARGET_USER) + if (!(moveTarget & MOVE_TARGET_USER)) { // handle negative checks on non-user target // check powder moves diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4d464c5d2..01944f508 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3504,8 +3504,11 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION; break; case MOVE_EFFECT_SCALE_SHOT: - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_DefDownSpeedUp; + if (!NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_DefDownSpeedUp; + } break; } } @@ -7700,6 +7703,7 @@ static bool32 CourtChangeSwapSideStatuses(void) UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId); UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId); UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId); + gBattleStruct->stickyWebUser ^= BIT_SIDE; // Track which side originally set the Sticky Web SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp); diff --git a/src/battle_util.c b/src/battle_util.c index 041661cdc..c0a7f2150 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1569,7 +1569,7 @@ void PrepareStringBattle(u16 stringId, u8 battler) && ((targetAbility == ABILITY_DEFIANT && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) || (targetAbility == ABILITY_COMPETITIVE && CompareStat(gBattlerTarget, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))) && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != BATTLE_PARTNER(gBattlerTarget) - // && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) // Why was this here? Needs investigating + && ((gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) || gBattleScripting.stickyWebStatDrop == 1) && !(gBattleScripting.stickyWebStatDrop == 1 && gSideTimers[targetSide].stickyWebBattlerSide == targetSide)) // Sticky Web must have been set by the foe { gBattleScripting.stickyWebStatDrop = 0; From 746d9ea6c52c523ebd52d765fd63b112e9933912 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 27 Apr 2022 22:23:20 +1200 Subject: [PATCH 28/29] Add AI_GetBattlerMoveTargetType() Add AI version of the function that handles move target selection, as it needs to have ability and item info that it may not have access to. --- include/battle_ai_util.h | 1 + src/battle_ai_main.c | 18 +++++++++--------- src/battle_ai_util.c | 12 +++++++++++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 5ccf68c58..0b2afebae 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -60,6 +60,7 @@ bool32 IsAbilityOfRating(u16 ability, s8 rating); s8 GetAbilityRating(u16 ability); bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability); bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move); +u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move); // stat stage checks bool32 AnyStatIsRaised(u8 battlerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 16e830efe..192b75d74 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -550,7 +550,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) u8 atkPriority = GetMovePriority(battlerAtk, move); u16 moveEffect = gBattleMoves[move].effect; s32 moveType; - u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); + u16 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move); u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move); u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef); bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); @@ -2371,7 +2371,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } else { - if (GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED + if (AI_GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_DEPENDS | MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH @@ -2568,7 +2568,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) // move data u8 moveType = gBattleMoves[move].type; u16 effect = gBattleMoves[move].effect; - u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); + u16 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move); // ally data u8 battlerAtkPartner = AI_DATA->battlerAtkPartner; u16 atkPartnerAbility = AI_DATA->atkPartnerAbility; @@ -2875,7 +2875,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (instructedMove != MOVE_NONE && !IS_MOVE_STATUS(instructedMove) - && (GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves + && (AI_GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves { RETURN_SCORE_PLUS(1); } @@ -3698,24 +3698,24 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_WIDE_GUARD: - if (predictedMove != MOVE_NONE && GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)) + if (predictedMove != MOVE_NONE && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)) { ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); } - else if (isDoubleBattle && GetBattlerMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) + else if (isDoubleBattle && AI_GetBattlerMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) { if (AI_DATA->atkAbility != ABILITY_TELEPATHY) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); } break; case MOVE_CRAFTY_SHIELD: - if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) + if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_MAT_BLOCK: if (gDisableStructs[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE - && !IS_MOVE_STATUS(predictedMove) && !(GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) + && !IS_MOVE_STATUS(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER)) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_KINGS_SHIELD: @@ -4160,7 +4160,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 10; break; case EFFECT_MAGIC_COAT: - if (IS_MOVE_STATUS(predictedMove) && GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) + if (IS_MOVE_STATUS(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) score += 3; break; case EFFECT_RECYCLE: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 4b344ecba..de4271bba 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1251,6 +1251,16 @@ bool32 AI_WeatherHasEffect(void) return TRUE; } +u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move) +{ + u32 target; + + if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && AI_IsTerrainAffected(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN)) + return MOVE_TARGET_BOTH; + else + return gBattleMoves[move].target; +} + bool32 IsAromaVeilProtectedMove(u16 move) { u32 i; @@ -1919,7 +1929,7 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32 if (ignoreStatus && IS_MOVE_STATUS(moves[i])) continue; else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0) - || GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) + || AI_GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD)) continue; if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck) return TRUE; From cbf0a6704b79f9d12d92ab0d91014e7ce9efde82 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 1 May 2022 12:54:33 +1200 Subject: [PATCH 29/29] Set Sticky Web user to Court Change user This is for Mirror Armor to track the current user of Sticky Web/the mon that caused the stat drop. --- src/battle_script_commands.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 01944f508..d6edb0ab2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7703,7 +7703,9 @@ static bool32 CourtChangeSwapSideStatuses(void) UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId); UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId); UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId); - gBattleStruct->stickyWebUser ^= BIT_SIDE; + + // For Mirror Armor only + gBattleStruct->stickyWebUser = gBattlerAttacker; // Track which side originally set the Sticky Web SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp);