Adds move Upper Hand (#4085)
* Remove non-existent tilesets from label comments and alphabetize * Fixed braces style * gbagfx bit depth upconversion fix * jsonproc: filter out every non-alphanumeric character * fix(linking): link gflib/malloc.c at top of EWRAM in ld_script_modern.ld * Adds move Upper Hand * Requested changes - Tabs / spaces where proper - HitFromAtkString -> HitFromAccCheck - Actually compiles now lol - Moved assumes into relevant tests - Cleaned up the check for TryUpperHand * Fixed || positioning * Update upper_hand.c * Revert "Merge remote-tracking branch 'upstream/master' into upper-hand" This reverts commitb21275dfe9
, reversing changes made to89b1ad1ea1
. * AI logic and conflicts solved * Test fix * Fix Sheer Force test * Requested changes * Requested changes * Update battle_script_commands.c --------- Co-authored-by: GriffinR <griffin.g.richards@gmail.com> Co-authored-by: Eduardo Quezada <eduardo602002@gmail.com> Co-authored-by: Sierraffinity <sierra@domoreaweso.me> Co-authored-by: sbird <sbird@no.tld>
This commit is contained in:
parent
6d3fa525d5
commit
71b49a114f
11 changed files with 191 additions and 4 deletions
|
@ -1583,6 +1583,11 @@
|
|||
callnative BS_SetPhotonGeyserCategory
|
||||
.endm
|
||||
|
||||
.macro tryupperhand failInstr:req
|
||||
callnative BS_TryUpperHand
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
@ various command changed to more readable macros
|
||||
.macro cancelmultiturnmoves battler:req
|
||||
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
|
||||
|
|
|
@ -17160,6 +17160,33 @@ Move_RAGING_BULL::
|
|||
waitbgfadein
|
||||
end
|
||||
|
||||
@ Credits to Z-nogyroP. Simple anim that combines Force Palm + Fake Out
|
||||
Move_UPPER_HAND::
|
||||
loadspritegfx ANIM_TAG_SHADOW_BALL
|
||||
loadspritegfx ANIM_TAG_HANDS_AND_FEET
|
||||
loadspritegfx ANIM_TAG_IMPACT
|
||||
monbg ANIM_DEF_PARTNER
|
||||
splitbgprio ANIM_TARGET
|
||||
setalpha 12, 8
|
||||
playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_TARGET
|
||||
createsprite gKarateChopSpriteTemplate, 2, 8, -16, 0, 0, 0, 10, 1, 3, 0
|
||||
waitforvisualfinish
|
||||
playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET
|
||||
createsprite gForcePalmSpriteTemplate 3, 4, 0, 0, 1, 2
|
||||
createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 4, 0, 6, 1
|
||||
waitforvisualfinish
|
||||
playsewithpan SE_M_FLATTER, 0
|
||||
createvisualtask AnimTask_FakeOut, 5
|
||||
waitforvisualfinish
|
||||
playsewithpan SE_M_SKETCH, SOUND_PAN_TARGET
|
||||
createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 4, 0, 5, 1
|
||||
createvisualtask AnimTask_StretchTargetUp, 3
|
||||
waitforvisualfinish
|
||||
createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 3, 16, 0, RGB_WHITE
|
||||
clearmonbg ANIM_DEF_PARTNER
|
||||
blendoff
|
||||
end
|
||||
|
||||
Move_TERA_BLAST::
|
||||
Move_AXE_KICK::
|
||||
Move_LAST_RESPECTS::
|
||||
|
@ -17215,7 +17242,6 @@ Move_DRAGON_CHEER::
|
|||
Move_TEMPER_FLARE::
|
||||
Move_SUPERCELL_SLAM::
|
||||
Move_PSYCHIC_NOISE::
|
||||
Move_UPPER_HAND::
|
||||
Move_MALIGNANT_CHAIN::
|
||||
end @to do
|
||||
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
|
||||
.section script_data, "aw", %progbits
|
||||
|
||||
BattleScript_EffectUpperHand::
|
||||
attackcanceler
|
||||
tryupperhand BattleScript_FailedFromAtkString
|
||||
goto BattleScript_HitFromAccCheck
|
||||
|
||||
BattleScript_EffectShedTail::
|
||||
attackcanceler
|
||||
attackstring
|
||||
|
|
|
@ -822,5 +822,6 @@ extern const u8 BattleScript_EffectBrickBreak[];
|
|||
extern const u8 BattleScript_EffectDoodle[];
|
||||
extern const u8 BattleScript_EffectFilletAway[];
|
||||
extern const u8 BattleScript_EffectShedTail[];
|
||||
extern const u8 BattleScript_EffectUpperHand[];
|
||||
|
||||
#endif // GUARD_BATTLE_SCRIPTS_H
|
||||
|
|
|
@ -351,6 +351,7 @@ enum {
|
|||
EFFECT_BLIZZARD,
|
||||
EFFECT_RAIN_ALWAYS_HIT, // Unlike EFFECT_THUNDER, it doesn't get its accuracy reduced under sun.
|
||||
EFFECT_SHED_TAIL,
|
||||
EFFECT_UPPER_HAND,
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
};
|
||||
|
||||
|
|
|
@ -2648,6 +2648,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (IsDynamaxed(battlerDef))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_UPPER_HAND:
|
||||
if (predictedMove == MOVE_NONE || IS_MOVE_STATUS(predictedMove) || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER || GetMovePriority(battlerDef, move) < 1 || GetMovePriority(battlerDef, move) > 3) // Opponent going first or not using priority move
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_PLACEHOLDER:
|
||||
return 0; // cannot even select
|
||||
} // move effect checks
|
||||
|
|
|
@ -1456,7 +1456,8 @@ static void Cmd_attackcanceler(void)
|
|||
else if (IsBattlerProtected(gBattlerTarget, gCurrentMove)
|
||||
&& (gCurrentMove != MOVE_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
|
||||
&& ((!gMovesInfo[gCurrentMove].twoTurnMove || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
|
||||
&& gMovesInfo[gCurrentMove].effect != EFFECT_SUCKER_PUNCH)
|
||||
&& gMovesInfo[gCurrentMove].effect != EFFECT_SUCKER_PUNCH
|
||||
&& gMovesInfo[gCurrentMove].effect != EFFECT_UPPER_HAND)
|
||||
{
|
||||
if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker))
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE;
|
||||
|
@ -5409,7 +5410,7 @@ static void Cmd_moveend(void)
|
|||
gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect;
|
||||
effect = 1;
|
||||
}
|
||||
else if (gProtectStructs[gBattlerTarget].obstructed && gCurrentMove != MOVE_SUCKER_PUNCH)
|
||||
else if (gProtectStructs[gBattlerTarget].obstructed && gMovesInfo[gCurrentMove].effect != EFFECT_SUCKER_PUNCH && gMovesInfo[gCurrentMove].effect != EFFECT_UPPER_HAND)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
|
||||
i = gBattlerAttacker;
|
||||
|
@ -16524,6 +16525,19 @@ void BS_TryDefog(void)
|
|||
}
|
||||
}
|
||||
|
||||
void BS_TryUpperHand(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)
|
||||
|| gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE
|
||||
|| IS_MOVE_STATUS(gChosenMoveByBattler[gBattlerTarget])
|
||||
|| GetChosenMovePriority(gBattlerTarget) < 1 || GetChosenMovePriority(gBattlerTarget) > 3) // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_TryTriggerStatusForm(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
|
|
@ -2223,4 +2223,10 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
|||
.battleScript = BattleScript_EffectShedTail,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_UPPER_HAND] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectUpperHand,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
};
|
||||
|
|
|
@ -19952,11 +19952,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
|
||||
[MOVE_UPPER_HAND] =
|
||||
{
|
||||
.effect = EFFECT_UPPER_HAND,
|
||||
.name = COMPOUND_STRING("Upper Hand"),
|
||||
.description = COMPOUND_STRING(
|
||||
"Makes the target flinch if\n"
|
||||
"readying a priority move."),
|
||||
.effect = EFFECT_PLACEHOLDER, //EFFECT_UPPER_HAND
|
||||
.power = 65,
|
||||
.type = TYPE_FIGHTING,
|
||||
.accuracy = 100,
|
||||
|
@ -19965,6 +19965,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
.priority = 3,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.sheerForceBoost = TRUE,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_FLINCH,
|
||||
.chance = 100,
|
||||
}),
|
||||
},
|
||||
|
||||
[MOVE_MALIGNANT_CHAIN] =
|
||||
|
|
|
@ -24,6 +24,8 @@ SINGLE_BATTLE_TEST("Sheer Force boosts power, but removes secondary effects of m
|
|||
} WHEN {
|
||||
if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect
|
||||
TURN { MOVE(opponent, MOVE_AGILITY); MOVE(player, move); }
|
||||
else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move
|
||||
TURN { MOVE(opponent, MOVE_QUICK_ATTACK); MOVE(player, move); }
|
||||
else
|
||||
TURN { MOVE(player, move); }
|
||||
if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE
|
||||
|
|
118
test/battle/move_effect/upper_hand.c
Normal file
118
test/battle/move_effect/upper_hand.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_UPPER_HAND].effect == EFFECT_UPPER_HAND);
|
||||
ASSUME(gMovesInfo[MOVE_UPPER_HAND].priority == 3);
|
||||
ASSUME(MoveHasMoveEffect(MOVE_UPPER_HAND, MOVE_EFFECT_FLINCH) == TRUE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Upper Hand succeeds if the target is using a priority attacking move and causes it to flinch")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_EXTREME_SPEED].category == DAMAGE_CATEGORY_PHYSICAL);
|
||||
ASSUME(gMovesInfo[MOVE_EXTREME_SPEED].priority == 2);
|
||||
PLAYER(SPECIES_MIENSHAO);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_EXTREME_SPEED); MOVE(player, MOVE_UPPER_HAND); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Foe Wobbuffet flinched!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EXTREME_SPEED, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Upper Hand fails if the target is using a status move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_BABY_DOLL_EYES].category == DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(gMovesInfo[MOVE_BABY_DOLL_EYES].priority == 1);
|
||||
PLAYER(SPECIES_MIENSHAO);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_BABY_DOLL_EYES); MOVE(player, MOVE_UPPER_HAND); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player);
|
||||
MESSAGE("Mienshao used Upper Hand!");
|
||||
MESSAGE("But it failed!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BABY_DOLL_EYES, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mienshao's Attack fell!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Upper Hand fails if the target is not using a priority move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_DRAINING_KISS].category == DAMAGE_CATEGORY_SPECIAL);
|
||||
ASSUME(gMovesInfo[MOVE_DRAINING_KISS].priority == 0);
|
||||
PLAYER(SPECIES_MIENSHAO);
|
||||
OPPONENT(SPECIES_COMFEY) { Ability(ABILITY_FLOWER_VEIL); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_DRAINING_KISS); MOVE(player, MOVE_UPPER_HAND); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player);
|
||||
MESSAGE("Mienshao used Upper Hand!");
|
||||
MESSAGE("But it failed!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAINING_KISS, opponent);
|
||||
HP_BAR(player);
|
||||
HP_BAR(opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Upper Hand succeeds if the target's move is boosted in priority by an Ability")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_DRAINING_KISS].category == DAMAGE_CATEGORY_SPECIAL);
|
||||
ASSUME(gMovesInfo[MOVE_DRAINING_KISS].priority == 0);
|
||||
PLAYER(SPECIES_MIENSHAO) { Speed(10); }
|
||||
OPPONENT(SPECIES_COMFEY) { Speed(5); Ability(ABILITY_TRIAGE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_DRAINING_KISS); MOVE(player, MOVE_UPPER_HAND); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("Foe Comfey flinched!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAINING_KISS, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Upper Hand fails if the target moves first")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_DRAINING_KISS].category == DAMAGE_CATEGORY_SPECIAL);
|
||||
ASSUME(gMovesInfo[MOVE_DRAINING_KISS].priority == 0);
|
||||
PLAYER(SPECIES_MIENSHAO) { Speed(5); }
|
||||
OPPONENT(SPECIES_COMFEY) { Speed(10); Ability(ABILITY_TRIAGE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_DRAINING_KISS); MOVE(player, MOVE_UPPER_HAND); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAINING_KISS, opponent);
|
||||
HP_BAR(player);
|
||||
HP_BAR(opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player);
|
||||
MESSAGE("Mienshao used Upper Hand!");
|
||||
MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Upper Hand is boosted by Sheer Force")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_EXTREME_SPEED].category == DAMAGE_CATEGORY_PHYSICAL);
|
||||
ASSUME(gMovesInfo[MOVE_EXTREME_SPEED].priority == 2);
|
||||
ASSUME(gMovesInfo[MOVE_UPPER_HAND].sheerForceBoost == TRUE);
|
||||
PLAYER(SPECIES_HARIYAMA) { Ability(ABILITY_SHEER_FORCE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_EXTREME_SPEED); MOVE(player, MOVE_UPPER_HAND); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_UPPER_HAND, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXTREME_SPEED, opponent);
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue