mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-04-26 10:25:49 -05:00
Adds smart target type (#8639)
This commit is contained in:
parent
f10d722af7
commit
5774dde7ae
|
|
@ -696,6 +696,7 @@ enum MoveTarget
|
|||
{
|
||||
TARGET_NONE,
|
||||
TARGET_SELECTED,
|
||||
TARGET_SMART, // Like target select but can also smartly redirect to partner. Works only with strikeCount > 1 moves
|
||||
TARGET_DEPENDS,
|
||||
TARGET_OPPONENT,
|
||||
TARGET_RANDOM,
|
||||
|
|
|
|||
|
|
@ -333,7 +333,6 @@ enum __attribute__((packed)) BattleMoveEffects
|
|||
EFFECT_SPICY_EXTRACT,
|
||||
EFFECT_TERA_BLAST,
|
||||
EFFECT_TERA_STARSTORM,
|
||||
EFFECT_DRAGON_DARTS,
|
||||
EFFECT_SHELL_SIDE_ARM,
|
||||
EFFECT_RAPID_SPIN,
|
||||
EFFECT_SPECTRAL_THIEF,
|
||||
|
|
|
|||
|
|
@ -246,7 +246,10 @@ static inline u32 GetMoveAccuracy(u32 moveId)
|
|||
|
||||
static inline u32 GetMoveTarget(u32 moveId)
|
||||
{
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].target;
|
||||
moveId = SanitizeMoveId(moveId);
|
||||
u32 target = gMovesInfo[moveId].target;
|
||||
assertf(target != TARGET_SMART || gMovesInfo[moveId].strikeCount > 1, "Smart target requires strikeCount > 1: %S", gMovesInfo[moveId].name);
|
||||
return target;
|
||||
}
|
||||
|
||||
static inline u32 GetMovePP(u32 moveId)
|
||||
|
|
|
|||
|
|
@ -3556,7 +3556,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
||||
if (GetMoveStrikeCount(move) > 1 && effect != EFFECT_DRAGON_DARTS)
|
||||
if (GetMoveStrikeCount(move) > 1 && moveTarget != TARGET_SMART)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3591,7 +3591,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
||||
if (GetMoveStrikeCount(move) > 1 && effect != EFFECT_DRAGON_DARTS)
|
||||
if (GetMoveStrikeCount(move) > 1 && moveTarget != TARGET_SMART)
|
||||
{
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
}
|
||||
|
|
@ -3649,7 +3649,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
|
||||
if (GetMoveStrikeCount(move) > 1 && effect != EFFECT_DRAGON_DARTS)
|
||||
if (GetMoveStrikeCount(move) > 1 && moveTarget != TARGET_SMART)
|
||||
{
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1478,10 +1478,9 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 pla
|
|||
|
||||
bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move)
|
||||
{
|
||||
enum BattleMoveEffects effect = GetMoveEffect(move);
|
||||
if (!AI_BattlerAtMaxHp(battlerTarget) || IsMultiHitMove(move) || gAiLogicData->abilities[battler] == ABILITY_PARENTAL_BOND)
|
||||
return FALSE;
|
||||
if (GetMoveStrikeCount(move) > 1 && !(effect == EFFECT_DRAGON_DARTS && !HasTwoOpponents(battler)))
|
||||
if (GetMoveStrikeCount(move) > 1 && !(AI_GetBattlerMoveTargetType(battler, move) == TARGET_SMART && !HasTwoOpponents(battler)))
|
||||
return FALSE;
|
||||
if (gAiLogicData->holdEffects[battlerTarget] == HOLD_EFFECT_FOCUS_SASH)
|
||||
return TRUE;
|
||||
|
|
@ -6289,6 +6288,7 @@ bool32 ShouldInstructPartner(u32 partner, u32 move)
|
|||
switch (type)
|
||||
{
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_SMART:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
|
|
@ -6311,6 +6311,7 @@ bool32 CanMoveBeBouncedBack(u32 battler, u32 move)
|
|||
switch (type)
|
||||
{
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_SMART:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
case TARGET_BOTH:
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -2017,7 +2017,7 @@ static void PlayerHandleChooseAction(u32 battler)
|
|||
u32 move = GetChosenMoveFromPosition(B_POSITION_PLAYER_RIGHT);
|
||||
StringAppend(gStringVar1, GetMoveName(move));
|
||||
enum MoveTarget moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move);
|
||||
if (moveTarget == TARGET_SELECTED)
|
||||
if (moveTarget == TARGET_SELECTED || moveTarget == TARGET_SMART)
|
||||
{
|
||||
if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_LEFT)
|
||||
StringAppend(gStringVar1, COMPOUND_STRING(" -{UP_ARROW}"));
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler)
|
|||
|
||||
if (moveTarget == TARGET_USER || moveTarget == TARGET_USER_OR_ALLY)
|
||||
chosenMoveIndex |= (battler << 8);
|
||||
else if (moveTarget == TARGET_SELECTED)
|
||||
else if (moveTarget == TARGET_SELECTED || moveTarget == TARGET_SMART)
|
||||
chosenMoveIndex |= GetBattlePalaceTarget(battler);
|
||||
else
|
||||
chosenMoveIndex |= (GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(battler))) << 8);
|
||||
|
|
@ -322,6 +322,7 @@ static u8 GetBattlePalaceMoveGroup(u8 battler, u16 move)
|
|||
switch (GetBattlerMoveTargetType(battler, move))
|
||||
{
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_SMART:
|
||||
case TARGET_OPPONENT:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
|
|
|
|||
|
|
@ -783,8 +783,9 @@ static enum MoveEndResult MoveEnd_MultihitMove(void)
|
|||
&& gMultiHitCounter
|
||||
&& !(moveEffect == EFFECT_PRESENT && gBattleStruct->presentBasePower == 0)) // Parental Bond edge case
|
||||
{
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
gMultiHitCounter--;
|
||||
if (!IsBattlerAlive(gBattlerTarget) && moveEffect != EFFECT_DRAGON_DARTS)
|
||||
if (!IsBattlerAlive(gBattlerTarget) && target != TARGET_SMART)
|
||||
gMultiHitCounter = 0;
|
||||
|
||||
gBattleScripting.multihitString[4]++;
|
||||
|
|
@ -798,7 +799,7 @@ static enum MoveEndResult MoveEnd_MultihitMove(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (moveEffect == EFFECT_DRAGON_DARTS
|
||||
if (target == TARGET_SMART
|
||||
&& !IsAffectedByFollowMe(gBattlerAttacker, GetBattlerSide(gBattlerTarget), gCurrentMove)
|
||||
&& !(gBattleStruct->moveResultFlags[BATTLE_PARTNER(gBattlerTarget)] & MOVE_RESULT_MISSED) // didn't miss the other target
|
||||
&& CanTargetPartner(gBattlerAttacker, gBattlerTarget)
|
||||
|
|
|
|||
|
|
@ -955,6 +955,7 @@ static bool32 NoTargetPresent(u8 battler, u32 move)
|
|||
switch (GetBattlerMoveTargetType(battler, move))
|
||||
{
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_SMART:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_RANDOM:
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
|
|
@ -1388,7 +1389,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
|||
if (holdEffectAtk == HOLD_EFFECT_BLUNDER_POLICY)
|
||||
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
||||
|
||||
if (effect == EFFECT_DRAGON_DARTS
|
||||
if (moveTarget == TARGET_SMART
|
||||
&& !IsAffectedByFollowMe(gBattlerAttacker, GetBattlerSide(battlerDef), gCurrentMove)
|
||||
&& !recalcDragonDarts // So we don't jump back and forth between targets
|
||||
&& CanTargetPartner(gBattlerAttacker, battlerDef)
|
||||
|
|
|
|||
|
|
@ -331,17 +331,6 @@ static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, enum
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static inline bool32 IsDragonDartsSecondHit(u32 effect)
|
||||
{
|
||||
if (effect != EFFECT_DRAGON_DARTS)
|
||||
return FALSE;
|
||||
|
||||
if (gMultiHitCounter == 1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsUnnerveBlocked(u32 battler, u32 itemId)
|
||||
{
|
||||
if (GetItemPocket(itemId) != POCKET_BERRIES)
|
||||
|
|
@ -381,13 +370,24 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static inline bool32 IsDragonDartsSecondHit(u32 battlerAtk, u32 move)
|
||||
{
|
||||
if (GetBattlerMoveTargetType(battlerAtk, move) != TARGET_SMART)
|
||||
return FALSE;
|
||||
|
||||
if (gMultiHitCounter < GetMoveStrikeCount(move))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|
||||
{
|
||||
enum Ability ability = GetBattlerAbility(battlerAtk);
|
||||
enum BattleMoveEffects effect = GetMoveEffect(move);
|
||||
|
||||
if (gSideTimers[defSide].followmeTimer == 0
|
||||
|| (!IsBattlerAlive(gSideTimers[defSide].followmeTarget) && !IsDragonDartsSecondHit(effect))
|
||||
|| (!IsBattlerAlive(gSideTimers[defSide].followmeTarget) && !IsDragonDartsSecondHit(battlerAtk, move))
|
||||
|| effect == EFFECT_SNIPE_SHOT
|
||||
|| effect == EFFECT_SKY_DROP
|
||||
|| IsAbilityAndRecord(battlerAtk, ability, ABILITY_PROPELLER_TAIL)
|
||||
|
|
@ -423,7 +423,7 @@ bool32 HandleMoveTargetRedirection(void)
|
|||
}
|
||||
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove)
|
||||
&& (moveTarget == TARGET_SELECTED || moveEffect == EFFECT_REFLECT_DAMAGE)
|
||||
&& (moveTarget == TARGET_SELECTED || moveTarget == TARGET_SMART || moveEffect == EFFECT_REFLECT_DAMAGE)
|
||||
&& !IsBattlerAlly(gBattlerAttacker, gSideTimers[side].followmeTarget))
|
||||
{
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = gSideTimers[side].followmeTarget; // follow me moxie fix
|
||||
|
|
@ -2959,7 +2959,7 @@ static enum MoveCanceler CancelerMultihitMoves(struct BattleContext *ctx)
|
|||
{
|
||||
gMultiHitCounter = GetMoveStrikeCount(ctx->move);
|
||||
|
||||
if (GetMoveEffect(ctx->move) == EFFECT_DRAGON_DARTS
|
||||
if (GetBattlerMoveTargetType(ctx->battlerAtk, ctx->move) == TARGET_SMART
|
||||
&& !IsAffectedByFollowMe(ctx->battlerAtk, GetBattlerSide(ctx->battlerDef), ctx->move)
|
||||
&& CanTargetPartner(ctx->battlerAtk, ctx->battlerDef)
|
||||
&& TargetFullyImmuneToCurrMove(ctx->battlerAtk, ctx->battlerDef))
|
||||
|
|
@ -11204,7 +11204,12 @@ void UpdateStallMons(void)
|
|||
{
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || GetMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_STATUS)
|
||||
return;
|
||||
if (!IsDoubleBattle() || GetMoveTarget(gCurrentMove) == TARGET_SELECTED)
|
||||
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
|
||||
if (!IsDoubleBattle()
|
||||
|| target == TARGET_SELECTED
|
||||
|| target == TARGET_SMART)
|
||||
{
|
||||
enum Type moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now
|
||||
enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||
|
|
|
|||
|
|
@ -5435,6 +5435,7 @@ static void SetMoveTargetPosition(u16 move)
|
|||
break;
|
||||
case TARGET_OPPONENT:
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_SMART:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
|
|
|
|||
|
|
@ -2239,12 +2239,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
|||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_DRAGON_DARTS] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
|
||||
[EFFECT_SHELL_SIDE_ARM] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
|
|
|
|||
|
|
@ -17875,12 +17875,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
|||
.description = COMPOUND_STRING(
|
||||
"The user attacks twice. Two\n"
|
||||
"targets are hit once each."),
|
||||
.effect = EFFECT_DRAGON_DARTS,
|
||||
.effect = EFFECT_HIT,
|
||||
.power = 50,
|
||||
.type = TYPE_DRAGON,
|
||||
.accuracy = 100,
|
||||
.pp = 10,
|
||||
.target = TARGET_SELECTED,
|
||||
.target = TARGET_SMART,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.strikeCount = 2,
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ DOUBLE_BATTLE_TEST("Commander Tatsugiri does not attack if Dondozo faints the sa
|
|||
DOUBLE_BATTLE_TEST("Commander Tatsugiri does not get hit by Dragon Darts when a commanded Dondozo faints")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_DRAGON_DARTS) == EFFECT_DRAGON_DARTS);
|
||||
ASSUME(GetMoveTarget(MOVE_DRAGON_DARTS) == TARGET_SMART);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_DONDOZO) { HP(1); }
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
|
|
@ -402,7 +402,7 @@ DOUBLE_BATTLE_TEST("Commander Tatsugiri does not get hit by Dragon Darts when co
|
|||
PARAMETRIZE { targetPlayerRight = TRUE; }
|
||||
PARAMETRIZE { targetPlayerRight = FALSE; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_DRAGON_DARTS) == EFFECT_DRAGON_DARTS);
|
||||
ASSUME(GetMoveTarget(MOVE_DRAGON_DARTS) == TARGET_SMART);
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
PLAYER(SPECIES_DONDOZO);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ DOUBLE_BATTLE_TEST("Neutralizing Gas is active for the duration of a Spread Move
|
|||
DOUBLE_BATTLE_TEST("Neutralizing Gas is active until the last Dragon Darts hit even if Neutralizing Gas is no longer on the field")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_DRAGON_DARTS) == EFFECT_DRAGON_DARTS);
|
||||
ASSUME(GetMoveTarget(MOVE_DRAGON_DARTS) == TARGET_SMART);
|
||||
PLAYER(SPECIES_WEEZING) { HP(1); Ability(ABILITY_NEUTRALIZING_GAS); }
|
||||
PLAYER(SPECIES_GOLEM) { HP(2); MaxHP(2); Ability(ABILITY_STURDY); }
|
||||
OPPONENT(SPECIES_BASCULEGION) { Ability(ABILITY_MOLD_BREAKER); }
|
||||
|
|
|
|||
|
|
@ -121,8 +121,8 @@ static u32 GetParametrizedLevel(u32 move, u32 variation)
|
|||
|
||||
static bool32 GetParametrizedShinyness(u32 move, u32 variation)
|
||||
{
|
||||
if ((gMovesInfo[move].effect == EFFECT_DRAGON_DARTS && variation == 2)
|
||||
|| (move == MOVE_SYRUP_BOMB && variation == 1)
|
||||
if ((GetMoveAnimationScript(move) == gBattleAnimMove_DragonDarts && variation == 2)
|
||||
|| (GetMoveAnimationScript(move) == gBattleAnimMove_SyrupBomb && variation == 1)
|
||||
)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
|
@ -194,7 +194,7 @@ static u32 GetVariationsNumber(u32 move, bool8 isDouble)
|
|||
variationsNumber = 4;
|
||||
else if (gMovesInfo[move].effect == EFFECT_SPIT_UP
|
||||
|| gMovesInfo[move].effect == EFFECT_SWALLOW
|
||||
|| gMovesInfo[move].effect == EFFECT_DRAGON_DARTS
|
||||
|| GetMoveAnimationScript(move) == gBattleAnimMove_DragonDarts
|
||||
|| move == MOVE_SEISMIC_TOSS)
|
||||
variationsNumber = 3;
|
||||
else if (gMovesInfo[move].effect == EFFECT_CURSE
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_DRAGON_DARTS) == EFFECT_DRAGON_DARTS);
|
||||
ASSUME(GetMoveTarget(MOVE_DRAGON_DARTS) == TARGET_SMART);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Dragon Darts strikes twice")
|
||||
|
|
|
|||
|
|
@ -2576,7 +2576,7 @@ s32 MoveGetTarget(s32 battlerId, u32 moveId, struct MoveContext *ctx, u32 source
|
|||
{
|
||||
target = BATTLE_OPPOSITE(battlerId);
|
||||
}
|
||||
else if (moveTarget == TARGET_SELECTED || moveTarget == TARGET_OPPONENT)
|
||||
else if (moveTarget == TARGET_SELECTED || moveTarget == TARGET_SMART || moveTarget == TARGET_OPPONENT)
|
||||
{
|
||||
// In AI Doubles not specified target allows any target for EXPECT_MOVE.
|
||||
if (GetBattleTest()->type != BATTLE_TEST_AI_DOUBLES)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user