mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Move target type refactor (#8513)
This commit is contained in:
parent
f621755397
commit
71a1967b7b
|
|
@ -1105,7 +1105,7 @@
|
|||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro callenvironmentattack
|
||||
.macro unused_0xCC
|
||||
.byte 0xcc
|
||||
.endm
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Let's look at an example:
|
|||
.type = TYPE_ELECTRIC,
|
||||
.accuracy = 100,
|
||||
.pp = 30,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.target = TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_SPECIAL,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
|
|
@ -170,7 +170,7 @@ Each move can have up to 3 additional effects, allowing you to construct monstro
|
|||
.type = TYPE_NORMAL,
|
||||
.accuracy = 100,
|
||||
.pp = 35,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.target = TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
|
|
|
|||
|
|
@ -1160,23 +1160,31 @@ static inline bool32 IsDoubleBattle(void)
|
|||
return (gBattleTypeFlags & BATTLE_TYPE_MORE_THAN_TWO_BATTLERS);
|
||||
}
|
||||
|
||||
static inline bool32 IsSpreadMove(u32 moveTarget)
|
||||
enum BattleTypeChecks
|
||||
{
|
||||
return IsDoubleBattle() && (moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY);
|
||||
CHECK_BATTLE_TYPE,
|
||||
IGNORE_BATTLE_TYPE,
|
||||
};
|
||||
|
||||
static inline bool32 IsSpreadMove(enum MoveTarget moveTarget, enum BattleTypeChecks checkBattleType)
|
||||
{
|
||||
if (checkBattleType == CHECK_BATTLE_TYPE && !IsDoubleBattle())
|
||||
return FALSE;
|
||||
return moveTarget == TARGET_BOTH || moveTarget == TARGET_FOES_AND_ALLY;
|
||||
}
|
||||
|
||||
static inline bool32 IsDoubleSpreadMove(void)
|
||||
{
|
||||
return gBattleStruct->numSpreadTargets > 1
|
||||
&& !gBattleStruct->unableToUseMove
|
||||
&& IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove));
|
||||
&& IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), CHECK_BATTLE_TYPE);
|
||||
}
|
||||
|
||||
static inline bool32 IsBattlerInvalidForSpreadMove(u32 battlerAtk, u32 battlerDef, u32 moveTarget)
|
||||
static inline bool32 IsBattlerInvalidForSpreadMove(u32 battlerAtk, u32 battlerDef, enum MoveTarget moveTarget)
|
||||
{
|
||||
return battlerDef == battlerAtk
|
||||
|| !IsBattlerAlive(battlerDef)
|
||||
|| (battlerDef == BATTLE_PARTNER(battlerAtk) && (moveTarget == MOVE_TARGET_BOTH));
|
||||
|| (battlerDef == BATTLE_PARTNER(battlerAtk) && moveTarget == TARGET_BOTH);
|
||||
}
|
||||
|
||||
static inline u32 GetChosenMoveFromPosition(u32 battler)
|
||||
|
|
|
|||
|
|
@ -329,6 +329,8 @@ u32 GetIncomingMoveSpeedCheck(u32 battler, u32 opposingBattler, struct AiLogicDa
|
|||
bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget);
|
||||
bool32 AI_OpponentCanFaintAiWithMod(u32 battler, u32 healAmount);
|
||||
void SetBattlerFieldStatusForSwitchin(u32 battler);
|
||||
bool32 ShouldInstructPartner(u32 battlerDef, u32 move);
|
||||
bool32 CanMoveBeBouncedBack(u32 battler, u32 move);
|
||||
|
||||
// Switching and item helpers
|
||||
bool32 AiExpectsToFaintPlayer(u32 battler);
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
|
|||
void ClearVariousBattlerFlags(u32 battler);
|
||||
void HandleAction_RunBattleScript(void);
|
||||
u32 SetRandomTarget(u32 battler);
|
||||
u32 GetBattleMoveTarget(u16 move, u8 setTarget);
|
||||
u32 GetBattleMoveTarget(u32 move, enum MoveTarget moveTarget);
|
||||
u8 GetAttackerObedienceForAction();
|
||||
enum HoldEffect GetBattlerHoldEffect(u32 battler);
|
||||
enum HoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler);
|
||||
|
|
|
|||
|
|
@ -689,19 +689,26 @@ enum BattleEnvironments
|
|||
// Indicator for the party summary bar to display an empty slot.
|
||||
#define HP_EMPTY_SLOT 0xFFFF
|
||||
|
||||
#define MOVE_TARGET_SELECTED 0
|
||||
#define MOVE_TARGET_DEPENDS (1 << 0)
|
||||
#define MOVE_TARGET_OPPONENT (1 << 1)
|
||||
#define MOVE_TARGET_RANDOM (1 << 2)
|
||||
#define MOVE_TARGET_BOTH (1 << 3)
|
||||
#define MOVE_TARGET_USER (1 << 4)
|
||||
#define MOVE_TARGET_FOES_AND_ALLY (1 << 5)
|
||||
#define MOVE_TARGET_OPPONENTS_FIELD (1 << 6)
|
||||
#define MOVE_TARGET_ALLY (1 << 7)
|
||||
#define MOVE_TARGET_ALL_BATTLERS ((1 << 8) | MOVE_TARGET_USER) // No functionality for status moves
|
||||
// (TARGET_USER | TARGET_ALLY)
|
||||
|
||||
// For the second argument of GetBattleMoveTarget, when no target override is needed
|
||||
#define NO_TARGET_OVERRIDE 0
|
||||
|
||||
enum MoveTarget
|
||||
{
|
||||
TARGET_NONE,
|
||||
TARGET_SELECTED,
|
||||
TARGET_DEPENDS,
|
||||
TARGET_OPPONENT,
|
||||
TARGET_RANDOM,
|
||||
TARGET_BOTH,
|
||||
TARGET_USER,
|
||||
TARGET_ALLY,
|
||||
TARGET_USER_AND_ALLY, // TODO: No functionality yet but would be used for howl in the future
|
||||
TARGET_USER_OR_ALLY, // Acupressure
|
||||
TARGET_FOES_AND_ALLY,
|
||||
TARGET_FIELD, // Moves that target the field, e.g. Rain Dance
|
||||
TARGET_OPPONENTS_FIELD, // Targets all other battlers and self, e.g. Teatime
|
||||
TARGET_ALL_BATTLERS,
|
||||
};
|
||||
|
||||
// Constants for Parental Bond
|
||||
#define PARENTAL_BOND_1ST_HIT 2
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ Refactors all battle animation move scripts, removing the list from `data/battle
|
|||
.type = TYPE_NORMAL,
|
||||
.accuracy = 100,
|
||||
.pp = 35,
|
||||
.target = MOVE_TARGET_SELECTED,
|
||||
.target = TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
|
|
|
|||
|
|
@ -1012,8 +1012,8 @@ static inline bool32 ShouldConsiderMoveForBattler(u32 battlerAi, u32 battlerDef,
|
|||
{
|
||||
if (battlerAi == BATTLE_PARTNER(battlerDef))
|
||||
{
|
||||
u32 target = AI_GetBattlerMoveTargetType(battlerAi, move);
|
||||
if (target == MOVE_TARGET_BOTH || target == MOVE_TARGET_OPPONENTS_FIELD)
|
||||
enum MoveTarget target = AI_GetBattlerMoveTargetType(battlerAi, move);
|
||||
if (target == TARGET_BOTH || target == TARGET_OPPONENTS_FIELD)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
|
@ -1244,7 +1244,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
ADJUST_SCORE(-5);
|
||||
|
||||
// check non-user target
|
||||
if (!(moveTarget & MOVE_TARGET_USER))
|
||||
if (moveTarget != TARGET_USER)
|
||||
{
|
||||
if (Ai_IsPriorityBlocked(battlerAtk, battlerDef, move, aiData))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
|
|
@ -1347,7 +1347,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
RETURN_SCORE_MINUS(20);
|
||||
break;
|
||||
case ABILITY_MAGIC_BOUNCE:
|
||||
if (MoveCanBeBouncedBack(move) && moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
if (CanMoveBeBouncedBack(battlerAtk, move))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
break;
|
||||
case ABILITY_SWEET_VEIL:
|
||||
|
|
@ -1370,7 +1370,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
// gen7+ dark type mons immune to priority->elevated moves from prankster
|
||||
if (GetConfig(CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)
|
||||
&& aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IsBattleMoveStatus(move)
|
||||
&& !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER)))
|
||||
&& moveTarget != TARGET_OPPONENTS_FIELD
|
||||
&& moveTarget != TARGET_USER)
|
||||
RETURN_SCORE_MINUS(10);
|
||||
|
||||
// terrain & effect checks
|
||||
|
|
@ -1390,7 +1391,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
{
|
||||
RETURN_SCORE_MINUS(20);
|
||||
}
|
||||
} // end check MOVE_TARGET_USER
|
||||
} // end check TARGET_USER
|
||||
|
||||
// the following checks apply to any target (including user)
|
||||
|
||||
|
|
@ -2395,7 +2396,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
}
|
||||
break;
|
||||
case PROTECT_WIDE_GUARD:
|
||||
if (!(AI_GetBattlerMoveTargetType(battlerAtk, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH)))
|
||||
if (!IsSpreadMove(AI_GetBattlerMoveTargetType(battlerAtk, predictedMove), IGNORE_BATTLE_TYPE))
|
||||
{
|
||||
ADJUST_SCORE(-10);
|
||||
decreased = TRUE;
|
||||
|
|
@ -2893,32 +2894,27 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
instructedMove = aiData->lastUsedMove[battlerDef];
|
||||
|
||||
if (instructedMove == MOVE_NONE
|
||||
|| IsMoveInstructBanned(instructedMove)
|
||||
|| MoveHasAdditionalEffectSelf(instructedMove, MOVE_EFFECT_RECHARGE)
|
||||
|| IsZMove(instructedMove)
|
||||
|| (gLockedMoves[battlerDef] != MOVE_NONE && gLockedMoves[battlerDef] != MOVE_UNAVAILABLE)
|
||||
|| gBattleMons[battlerDef].volatiles.multipleTurns
|
||||
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
|| IsMoveInstructBanned(instructedMove)
|
||||
|| MoveHasAdditionalEffectSelf(instructedMove, MOVE_EFFECT_RECHARGE)
|
||||
|| IsZMove(instructedMove)
|
||||
|| (gLockedMoves[battlerDef] != MOVE_NONE && gLockedMoves[battlerDef] != MOVE_UNAVAILABLE)
|
||||
|| gBattleMons[battlerDef].volatiles.multipleTurns
|
||||
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
|
||||
{
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX)
|
||||
{
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
else if (hasPartner)
|
||||
{
|
||||
if (!IsTargetingPartner(battlerAtk, battlerDef))
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
else
|
||||
else if (ShouldInstructPartner(battlerDef, instructedMove))
|
||||
{
|
||||
if (AI_GetBattlerMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED
|
||||
| MOVE_TARGET_DEPENDS
|
||||
| MOVE_TARGET_RANDOM
|
||||
| MOVE_TARGET_BOTH
|
||||
| MOVE_TARGET_FOES_AND_ALLY
|
||||
| MOVE_TARGET_OPPONENTS_FIELD)
|
||||
&& GetMoveEffect(instructedMove) != EFFECT_MAX_HP_50_RECOIL)
|
||||
ADJUST_SCORE(-10); //Don't force the enemy to attack you again unless it can kill itself with Mind Blown
|
||||
ADJUST_SCORE(-10); //Don't force the enemy to attack you again unless it can kill itself with Mind Blown
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -3104,7 +3100,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (IsHoldEffectChoice(aiData->holdEffects[battlerAtk]) && IsBattlerItemEnabled(battlerAtk))
|
||||
{
|
||||
// Don't use user-target moves ie. Swords Dance, with exceptions
|
||||
if ((moveTarget & MOVE_TARGET_USER)
|
||||
if ((moveTarget == TARGET_USER)
|
||||
&& moveEffect != EFFECT_DESTINY_BOND && moveEffect != EFFECT_WISH && moveEffect != EFFECT_HEALING_WISH
|
||||
&& !(moveEffect == EFFECT_AURORA_VEIL && (AI_GetWeather() & B_WEATHER_ICY_ANY)))
|
||||
ADJUST_SCORE(-30);
|
||||
|
|
@ -3240,7 +3236,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (IsAttackBoostMoveEffect(effect))
|
||||
ADJUST_SCORE(-3);
|
||||
// encourage moves hitting multiple opponents
|
||||
if (!IsBattleMoveStatus(move) && (moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
if (!IsBattleMoveStatus(move) && IsSpreadMove(moveTarget, IGNORE_BATTLE_TYPE))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
}
|
||||
|
|
@ -3361,7 +3357,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
} // global move effect check
|
||||
|
||||
// Specific logic for spread moves.
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
// Don't kill your partner for no reason.
|
||||
if (wouldPartnerFaint)
|
||||
|
|
@ -3459,7 +3455,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
}
|
||||
|
||||
// partner ability checks
|
||||
if (!partnerProtecting && moveTarget != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
|
||||
if (!partnerProtecting && moveTarget != TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
|
||||
{
|
||||
switch (atkPartnerAbility)
|
||||
{
|
||||
|
|
@ -3471,7 +3467,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
{
|
||||
if (MoveAlwaysCrits(move))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3494,7 +3490,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
RETURN_SCORE_MINUS(10);
|
||||
}
|
||||
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3516,7 +3512,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case ABILITY_LEVITATE:
|
||||
if (moveType == TYPE_GROUND)
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3540,7 +3536,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
RETURN_SCORE_MINUS(10);
|
||||
}
|
||||
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3562,7 +3558,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (moveType == TYPE_WATER && isFriendlyFireOK
|
||||
&& ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3581,7 +3577,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
if (isFriendlyFireOK && (moveType == TYPE_WATER || moveType == TYPE_FIRE)
|
||||
&& ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3597,7 +3593,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
&& !IsBattleMoveStatus(move)
|
||||
&& ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3618,7 +3614,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case ABILITY_WELL_BAKED_BODY:
|
||||
if (moveType == TYPE_FIRE)
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3635,7 +3631,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case ABILITY_SAP_SIPPER:
|
||||
if (moveType == TYPE_GRASS)
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3655,7 +3651,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
&& !IsBattleMoveStatus(move)
|
||||
&& ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
|
|
@ -3677,7 +3673,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
&& (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG)
|
||||
&& ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
|
|
@ -3693,7 +3689,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case ABILITY_COMPETITIVE:
|
||||
if (IsStatLoweringEffect(effect) && isFriendlyFireOK && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility))
|
||||
{
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
|
|
@ -3795,15 +3791,13 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
break;
|
||||
case EFFECT_INSTRUCT:
|
||||
{
|
||||
u16 instructedMove;
|
||||
u32 instructedMove = aiData->lastUsedMove[battlerAtkPartner];
|
||||
if (AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY))
|
||||
instructedMove = aiData->partnerMove;
|
||||
else
|
||||
instructedMove = aiData->lastUsedMove[battlerAtkPartner];
|
||||
|
||||
if (instructedMove != MOVE_NONE
|
||||
&& !IsBattleMoveStatus(instructedMove)
|
||||
&& (AI_GetBattlerMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves
|
||||
&& !IsBattleMoveStatus(instructedMove)
|
||||
&& IsSpreadMove(AI_GetBattlerMoveTargetType(battlerAtkPartner, instructedMove), IGNORE_BATTLE_TYPE))
|
||||
{
|
||||
RETURN_SCORE_PLUS(WEAK_EFFECT);
|
||||
}
|
||||
|
|
@ -4006,7 +4000,7 @@ static inline bool32 ShouldUseSpreadDamageMove(u32 battlerAtk, u32 move, u32 mov
|
|||
u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk);
|
||||
return (HasPartnerIgnoreFlags(battlerAtk)
|
||||
&& noOfHitsToFaintPartner != 0 // Immunity check
|
||||
&& AI_GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_FOES_AND_ALLY
|
||||
&& AI_GetBattlerMoveTargetType(battlerAtk, move) == TARGET_FOES_AND_ALLY
|
||||
&& !(noOfHitsToFaintPartner < friendlyFireThreshold && hitsToFaintOpposingBattler == 1)
|
||||
&& noOfHitsToFaintPartner < (friendlyFireThreshold * 2));
|
||||
}
|
||||
|
|
@ -4242,7 +4236,8 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
|||
bool32 isBattle1v1 = IsBattle1v1();
|
||||
bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk);
|
||||
bool32 hasPartner = HasPartner(battlerAtk);
|
||||
bool32 moveTargetsBothOpponents = hasTwoOpponents && (GetMoveTarget(move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_ALL_BATTLERS));
|
||||
enum MoveTarget moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
bool32 moveTargetsBothOpponents = hasTwoOpponents && (IsSpreadMove(moveTarget, IGNORE_BATTLE_TYPE) || moveTarget == TARGET_ALL_BATTLERS || moveTarget == TARGET_FIELD);
|
||||
u32 i;
|
||||
|
||||
// The AI should understand that while Dynamaxed, status moves function like Protect.
|
||||
|
|
@ -4784,24 +4779,24 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
|||
}
|
||||
break;
|
||||
case PROTECT_WIDE_GUARD:
|
||||
if (predictedMove != MOVE_NONE && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
if (predictedMove != MOVE_NONE && IsSpreadMove(AI_GetBattlerMoveTargetType(battlerDef, predictedMove), IGNORE_BATTLE_TYPE))
|
||||
{
|
||||
ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove));
|
||||
}
|
||||
else if (hasPartner && AI_GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (hasPartner && AI_GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
if (aiData->abilities[battlerAtk] != ABILITY_TELEPATHY)
|
||||
ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove));
|
||||
}
|
||||
break;
|
||||
case PROTECT_CRAFTY_SHIELD:
|
||||
if (predictedMove != MOVE_NONE && IsBattleMoveStatus(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
if (predictedMove != MOVE_NONE && IsBattleMoveStatus(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) != TARGET_USER)
|
||||
ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove));
|
||||
break;
|
||||
|
||||
case PROTECT_MAT_BLOCK:
|
||||
if (gBattleStruct->battlerState[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE
|
||||
&& !IsBattleMoveStatus(predictedMove) && !(AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
&& !IsBattleMoveStatus(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) != TARGET_USER)
|
||||
ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove));
|
||||
break;
|
||||
case PROTECT_KINGS_SHIELD:
|
||||
|
|
@ -5075,7 +5070,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
|||
break;
|
||||
case EFFECT_FOLLOW_ME:
|
||||
if (hasPartner
|
||||
&& GetMoveTarget(move) == MOVE_TARGET_USER
|
||||
&& AI_GetBattlerMoveTargetType(battlerAtk, move) == TARGET_USER
|
||||
&& !IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef])
|
||||
&& (!IsPowderMove(move) || IsAffectedByPowderMove(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])))
|
||||
// Rage Powder doesn't affect powder immunities
|
||||
|
|
@ -5214,7 +5209,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
|||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_MAGIC_COAT:
|
||||
if (IsBattleMoveStatus(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
if (CanMoveBeBouncedBack(battlerDef, predictedMove))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_RECYCLE:
|
||||
|
|
@ -6014,7 +6009,9 @@ static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, u32 move
|
|||
break;
|
||||
case MOVE_EFFECT_CLEAR_SMOG:
|
||||
{
|
||||
bool32 moveTargetsBothOpponents = HasTwoOpponents(battlerAtk) && (gMovesInfo[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_ALL_BATTLERS));
|
||||
enum MoveTarget target = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
bool32 moveTargetsBothOpponents = HasTwoOpponents(battlerAtk)
|
||||
&& (target == TARGET_FIELD || target == TARGET_ALL_BATTLERS || IsSpreadMove(target, IGNORE_BATTLE_TYPE));
|
||||
|
||||
score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents);
|
||||
break;
|
||||
|
|
@ -6416,7 +6413,7 @@ static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|
|||
|
||||
u32 hitsToKO = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING, CONSIDER_ENDURE);
|
||||
|
||||
if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY && hitsToKO > 0 &&
|
||||
if (AI_GetBattlerMoveTargetType(battlerAtk, move) == TARGET_FOES_AND_ALLY && hitsToKO > 0 &&
|
||||
(GetNoOfHitsToKOBattler(battlerAtk, LEFT_FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING, CONSIDER_ENDURE) > 0 || GetNoOfHitsToKOBattler(battlerAtk, LEFT_FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING, CONSIDER_ENDURE) > 0))
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move)
|
|||
u32 numOfTargets = 0;
|
||||
u32 moveTargetType = AI_GetBattlerMoveTargetType(battlerAtk, move);
|
||||
|
||||
if (!IsSpreadMove(moveTargetType))
|
||||
if (!IsSpreadMove(moveTargetType, CHECK_BATTLE_TYPE))
|
||||
return FALSE;
|
||||
|
||||
for (u32 battlerDef = 0; battlerDef < MAX_BATTLERS_COUNT; battlerDef++)
|
||||
|
|
@ -51,7 +51,7 @@ static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move)
|
|||
if (battlerAtk == battlerDef)
|
||||
continue;
|
||||
|
||||
if (moveTargetType == MOVE_TARGET_BOTH && battlerAtk == BATTLE_PARTNER(battlerDef))
|
||||
if (moveTargetType == TARGET_BOTH && battlerAtk == BATTLE_PARTNER(battlerDef))
|
||||
continue;
|
||||
|
||||
if (IsBattlerAlive(battlerDef) && !IsSemiInvulnerable(battlerDef, move))
|
||||
|
|
@ -73,11 +73,11 @@ u32 AI_GetBattlerMoveTargetType(u32 battler, u32 move)
|
|||
{
|
||||
enum BattleMoveEffects effect = GetMoveEffect(move);
|
||||
if (effect == EFFECT_CURSE && !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return MOVE_TARGET_USER;
|
||||
return TARGET_USER;
|
||||
if (effect == EFFECT_EXPANDING_FORCE && IsPsychicTerrainAffected(battler, gAiLogicData->abilities[battler], gAiLogicData->holdEffects[battler], gFieldStatuses))
|
||||
return MOVE_TARGET_BOTH;
|
||||
return TARGET_BOTH;
|
||||
if (effect == EFFECT_TERA_STARSTORM && gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
return MOVE_TARGET_BOTH;
|
||||
return TARGET_BOTH;
|
||||
|
||||
return GetMoveTarget(move);
|
||||
}
|
||||
|
|
@ -2853,8 +2853,12 @@ bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool
|
|||
|
||||
if (ignoreStatus && IsBattleMoveStatus(moves[i]))
|
||||
continue;
|
||||
else if ((!IsBattleMoveStatus(moves[i]) && GetMoveAccuracy(moves[i]) == 0)
|
||||
|| AI_GetBattlerMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
|
||||
if (!IsBattleMoveStatus(moves[i]) && GetMoveAccuracy(moves[i]) == 0)
|
||||
continue;
|
||||
|
||||
enum MoveTarget target = AI_GetBattlerMoveTargetType(battlerAtk, moves[i]);
|
||||
if (target == TARGET_USER || target == TARGET_OPPONENTS_FIELD)
|
||||
continue;
|
||||
|
||||
if (gAiLogicData->moveAccuracy[battlerAtk][battlerDef][i] <= accCheck)
|
||||
|
|
@ -3709,7 +3713,7 @@ bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability a
|
|||
|
||||
bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove)
|
||||
{
|
||||
if (AI_GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_FOES_AND_ALLY
|
||||
if (AI_GetBattlerMoveTargetType(battlerAtk, move) == TARGET_FOES_AND_ALLY
|
||||
&& AI_CanBeConfused(battlerAtk, battlerDef, move, defAbility)
|
||||
&& !AI_CanBeConfused(battlerAtk, BATTLE_PARTNER(battlerDef), move, gAiLogicData->abilities[BATTLE_PARTNER(battlerDef)]))
|
||||
return FALSE;
|
||||
|
|
@ -4223,7 +4227,7 @@ bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 p
|
|||
// shared bits indicate they're meaningfully the same in some way
|
||||
if (atkEffect & partnerEffect)
|
||||
{
|
||||
if (GetMoveTarget(move) == MOVE_TARGET_SELECTED && GetMoveTarget(partnerMove) == MOVE_TARGET_SELECTED)
|
||||
if (GetMoveTarget(move) == TARGET_SELECTED && GetMoveTarget(partnerMove) == TARGET_SELECTED)
|
||||
{
|
||||
if (battlerDef == gBattleStruct->moveTarget[battlerAtkPartner])
|
||||
return TRUE;
|
||||
|
|
@ -4368,7 +4372,7 @@ bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32
|
|||
if (GetMoveEffect(move) == GetMoveEffect(partnerMove)
|
||||
&& partnerMove != MOVE_NONE)
|
||||
{
|
||||
if (GetMoveTarget(move) == MOVE_TARGET_SELECTED && GetMoveTarget(partnerMove) == MOVE_TARGET_SELECTED)
|
||||
if (GetMoveTarget(move) == TARGET_SELECTED && GetMoveTarget(partnerMove) == TARGET_SELECTED)
|
||||
{
|
||||
return gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef;
|
||||
}
|
||||
|
|
@ -5196,9 +5200,9 @@ bool32 IsConsideringZMove(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
//TODO - this could use some more sophisticated logic
|
||||
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove)
|
||||
{
|
||||
|
||||
// simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent
|
||||
if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk) && !(AI_GetBattlerMoveTargetType(battlerAtk, chosenMove) & MOVE_TARGET_ALLY))
|
||||
enum MoveTarget target = AI_GetBattlerMoveTargetType(battlerAtk, chosenMove);
|
||||
if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk) && target != TARGET_ALLY && target != TARGET_USER_OR_ALLY)
|
||||
return FALSE; // don't use z move on partner
|
||||
if (HasTrainerUsedGimmick(battlerAtk, GIMMICK_Z_MOVE))
|
||||
return FALSE; // can't use z move twice
|
||||
|
|
@ -6340,3 +6344,44 @@ void GetAIPartyIndexes(u32 battler, s32 *firstId, s32 *lastId)
|
|||
*firstId = 0, *lastId = PARTY_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
bool32 ShouldInstructPartner(u32 partner, u32 move)
|
||||
{
|
||||
if (GetMoveEffect(move) == EFFECT_MAX_HP_50_RECOIL && gAiLogicData->abilities[partner] != ABILITY_MAGIC_GUARD)
|
||||
return FALSE;
|
||||
|
||||
enum MoveTarget type = AI_GetBattlerMoveTargetType(partner, move);
|
||||
switch (type)
|
||||
{
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 CanMoveBeBouncedBack(u32 battler, u32 move)
|
||||
{
|
||||
if (!MoveCanBeBouncedBack(move) || !IsBattleMoveStatus(move))
|
||||
return FALSE;
|
||||
|
||||
enum MoveTarget type = AI_GetBattlerMoveTargetType(battler, move);
|
||||
switch (type)
|
||||
{
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
case TARGET_BOTH:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ void DoMoveAnim(u16 move)
|
|||
gBattleAnimAttacker = gBattlerAttacker;
|
||||
gBattleAnimTarget = gBattlerTarget;
|
||||
// Make sure the anim target of moves hitting everyone is at the opposite side.
|
||||
if (GetBattlerMoveTargetType(gBattlerAttacker, move) & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle())
|
||||
if (GetBattlerMoveTargetType(gBattleAnimAttacker, move) == TARGET_FOES_AND_ALLY && IsDoubleBattle())
|
||||
{
|
||||
while (IsBattlerAlly(gBattleAnimAttacker, gBattleAnimTarget))
|
||||
{
|
||||
|
|
@ -552,7 +552,7 @@ static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets)
|
|||
|
||||
switch (target)
|
||||
{
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
if (battlerAnimId == ANIM_ATTACKER)
|
||||
{
|
||||
targets[numTargets++] = gBattleAnimAttacker;
|
||||
|
|
@ -566,7 +566,7 @@ static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_TARGET_BOTH: // all opponents
|
||||
case TARGET_BOTH: // all opponents
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (i != ignoredTgt && !IsBattlerAlly(i, ignoredTgt) && IS_ALIVE_AND_PRESENT(i))
|
||||
|
|
|
|||
|
|
@ -4957,7 +4957,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite)
|
|||
{
|
||||
if (gBattleAnimArgs[0] == 0)
|
||||
{
|
||||
if (GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH)
|
||||
if (GetMoveTarget(gAnimMoveIndex) == TARGET_BOTH)
|
||||
{
|
||||
SetAverageBattlerPositions(gBattleAnimAttacker, TRUE, &a, &b);
|
||||
}
|
||||
|
|
@ -4969,7 +4969,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH)
|
||||
if (GetMoveTarget(gAnimMoveIndex) == TARGET_BOTH)
|
||||
{
|
||||
SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &a, &b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ static void AnimWillOWispFire(struct Sprite *sprite)
|
|||
if (IsDoubleBattle()
|
||||
&& !IsContest()
|
||||
&& IsBattlerAlive(BATTLE_PARTNER(gBattleAnimTarget))
|
||||
&& GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH)
|
||||
&& GetMoveTarget(gAnimMoveIndex) == TARGET_BOTH)
|
||||
SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->x, &sprite->y);
|
||||
|
||||
sprite->x2 = Sin(sprite->data[1], sprite->data[3] >> 8);
|
||||
|
|
|
|||
|
|
@ -8120,7 +8120,7 @@ static void SpriteCB_MaxFlutterby(struct Sprite* sprite)
|
|||
{
|
||||
s16 target_x;
|
||||
s16 target_y;
|
||||
if (GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH)
|
||||
if (GetMoveTarget(gAnimMoveIndex) == TARGET_BOTH)
|
||||
{
|
||||
SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &target_x, &target_y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,13 +385,13 @@ u32 UnpackSelectedBattlePalettes(s16 selector)
|
|||
|
||||
switch (moveTarget)
|
||||
{
|
||||
case MOVE_TARGET_BOTH:
|
||||
case TARGET_BOTH:
|
||||
if (target)
|
||||
{
|
||||
targetPartner |= 1;
|
||||
}
|
||||
break;
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
if (target)
|
||||
{
|
||||
targetPartner |= 1;
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ void AnimRockFragment(struct Sprite *sprite)
|
|||
// args[6] - attacker or target
|
||||
void AnimParticleInVortex(struct Sprite *sprite)
|
||||
{
|
||||
if (IsDoubleBattle() && GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH)
|
||||
if (IsDoubleBattle() && GetMoveTarget(gAnimMoveIndex) == TARGET_BOTH)
|
||||
InitSpritePosToAnimTargetsCentre(sprite, FALSE);
|
||||
else
|
||||
InitSpritePosToAnimBattler(gBattleAnimArgs[6], sprite, FALSE);
|
||||
|
|
|
|||
|
|
@ -454,9 +454,12 @@ static void OpponentHandleChooseMove(u32 battler)
|
|||
gBattlerTarget = gAiBattleData->chosenTarget[battler];
|
||||
|
||||
u32 chosenMove = moveInfo->moves[chosenMoveIndex];
|
||||
if (GetBattlerMoveTargetType(battler, chosenMove) & MOVE_TARGET_USER)
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(battler, chosenMove);
|
||||
|
||||
if (target == TARGET_USER || target == TARGET_USER_OR_ALLY)
|
||||
gBattlerTarget = battler;
|
||||
if (GetBattlerMoveTargetType(battler, chosenMove) & MOVE_TARGET_BOTH)
|
||||
|
||||
if (target == TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
if (gAbsentBattlerFlags & (1u << gBattlerTarget))
|
||||
|
|
@ -480,14 +483,14 @@ static void OpponentHandleChooseMove(u32 battler)
|
|||
else // Wild pokemon - use random move
|
||||
{
|
||||
u32 move;
|
||||
u32 target;
|
||||
do
|
||||
{
|
||||
chosenMoveIndex = Random() & (MAX_MON_MOVES - 1);
|
||||
move = moveInfo->moves[chosenMoveIndex];
|
||||
} while (move == MOVE_NONE);
|
||||
|
||||
if (GetBattlerMoveTargetType(battler, move) & MOVE_TARGET_USER)
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(battler, move);
|
||||
if (target == TARGET_USER || target == TARGET_USER_OR_ALLY)
|
||||
{
|
||||
BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (battler << 8));
|
||||
}
|
||||
|
|
@ -498,7 +501,7 @@ static void OpponentHandleChooseMove(u32 battler)
|
|||
} while (!CanTargetBattler(battler, target, move));
|
||||
|
||||
// Don't bother to check if they're enemies if the move can't attack ally
|
||||
if (B_WILD_NATURAL_ENEMIES == TRUE && !(GetBattlerMoveTargetType(battler, move) & MOVE_TARGET_BOTH))
|
||||
if (B_WILD_NATURAL_ENEMIES == TRUE && GetBattlerMoveTargetType(battler, move) != TARGET_BOTH)
|
||||
{
|
||||
u32 speciesAttacker, speciesTarget;
|
||||
speciesAttacker = gBattleMons[battler].species;
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ void HandleInputChooseTarget(u32 battler)
|
|||
PlaySE(SE_SELECT);
|
||||
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCB_HideAsMoveTarget;
|
||||
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
if (moveTarget == TARGET_USER_OR_ALLY)
|
||||
{
|
||||
gMultiUsePlayerCursor ^= BIT_FLANK;
|
||||
}
|
||||
|
|
@ -500,7 +500,7 @@ void HandleInputChooseTarget(u32 battler)
|
|||
|
||||
if (gAbsentBattlerFlags & (1u << gMultiUsePlayerCursor)
|
||||
|| !CanTargetBattler(battler, gMultiUsePlayerCursor, move)
|
||||
|| (moveTarget & MOVE_TARGET_OPPONENT && IsOnPlayerSide(gMultiUsePlayerCursor)))
|
||||
|| (moveTarget == TARGET_OPPONENT && IsOnPlayerSide(gMultiUsePlayerCursor)))
|
||||
i = 0;
|
||||
} while (i == 0);
|
||||
}
|
||||
|
|
@ -511,7 +511,7 @@ void HandleInputChooseTarget(u32 battler)
|
|||
PlaySE(SE_SELECT);
|
||||
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCB_HideAsMoveTarget;
|
||||
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
if (moveTarget == TARGET_USER_OR_ALLY)
|
||||
{
|
||||
gMultiUsePlayerCursor ^= BIT_FLANK;
|
||||
}
|
||||
|
|
@ -551,7 +551,7 @@ void HandleInputChooseTarget(u32 battler)
|
|||
|
||||
if (gAbsentBattlerFlags & (1u << gMultiUsePlayerCursor)
|
||||
|| !CanTargetBattler(battler, gMultiUsePlayerCursor, move)
|
||||
|| (moveTarget & MOVE_TARGET_OPPONENT && IsOnPlayerSide(gMultiUsePlayerCursor)))
|
||||
|| (moveTarget == TARGET_OPPONENT && IsOnPlayerSide(gMultiUsePlayerCursor)))
|
||||
i = 0;
|
||||
} while (i == 0);
|
||||
}
|
||||
|
|
@ -652,9 +652,28 @@ static void TryShowAsTarget(u32 battler)
|
|||
}
|
||||
}
|
||||
|
||||
static bool32 CanSelectBattler(enum MoveTarget target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
case TARGET_USER:
|
||||
case TARGET_ALLY:
|
||||
case TARGET_USER_OR_ALLY:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void HandleInputChooseMove(u32 battler)
|
||||
{
|
||||
u16 moveTarget;
|
||||
u32 canSelectTarget = 0;
|
||||
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]);
|
||||
|
||||
|
|
@ -668,36 +687,37 @@ void HandleInputChooseMove(u32 battler)
|
|||
TryToHideMoveInfoWindow();
|
||||
PlaySE(SE_SELECT);
|
||||
|
||||
moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[gMoveSelectionCursor[battler]]);
|
||||
enum MoveTarget moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[gMoveSelectionCursor[battler]]);
|
||||
bool32 isUserOrAlly = moveTarget == TARGET_USER || moveTarget == TARGET_USER_OR_ALLY;
|
||||
|
||||
if (gBattleStruct->zmove.viewing)
|
||||
{
|
||||
gBattleStruct->zmove.viewing = FALSE;
|
||||
if (GetMoveCategory(moveInfo->moves[gMoveSelectionCursor[battler]]) != DAMAGE_CATEGORY_STATUS)
|
||||
moveTarget = MOVE_TARGET_SELECTED; //damaging z moves always have selected target
|
||||
moveTarget = TARGET_SELECTED; //damaging z moves always have selected target
|
||||
}
|
||||
|
||||
// Status moves turn into Max Guard when Dynamaxed, targets user.
|
||||
if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX))
|
||||
moveTarget = GetMoveTarget(GetMaxMove(battler, moveInfo->moves[gMoveSelectionCursor[battler]]));
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
if (isUserOrAlly)
|
||||
gMultiUsePlayerCursor = battler;
|
||||
else
|
||||
gMultiUsePlayerCursor = GetOpposingSideBattler(battler);
|
||||
|
||||
if (gBattleResources->bufferA[battler][1]) // a double battle
|
||||
{
|
||||
if (!(moveTarget & (MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH | MOVE_TARGET_DEPENDS | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER | MOVE_TARGET_ALLY)))
|
||||
if (!CanSelectBattler(moveTarget))
|
||||
canSelectTarget = 1; // either selected or user
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY) && IsBattlerAlive(BATTLE_PARTNER(battler)))
|
||||
if (moveTarget == TARGET_USER_OR_ALLY && IsBattlerAlive(BATTLE_PARTNER(battler)))
|
||||
canSelectTarget = 1;
|
||||
|
||||
if (moveInfo->currentPp[gMoveSelectionCursor[battler]] == 0)
|
||||
{
|
||||
canSelectTarget = 0;
|
||||
}
|
||||
else if (!(moveTarget & MOVE_TARGET_USER) && CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, battler) <= 1)
|
||||
else if (isUserOrAlly && CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, battler) <= 1)
|
||||
{
|
||||
gMultiUsePlayerCursor = GetDefaultMoveTarget(battler);
|
||||
canSelectTarget = 0;
|
||||
|
|
@ -706,7 +726,7 @@ void HandleInputChooseMove(u32 battler)
|
|||
if (B_SHOW_TARGETS == TRUE)
|
||||
{
|
||||
// Show all available targets for multi-target moves
|
||||
if ((moveTarget & MOVE_TARGET_ALL_BATTLERS) == MOVE_TARGET_ALL_BATTLERS)
|
||||
if (moveTarget == TARGET_ALL_BATTLERS || moveTarget == TARGET_FIELD)
|
||||
{
|
||||
u32 i = 0;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
|
|
@ -714,11 +734,11 @@ void HandleInputChooseMove(u32 battler)
|
|||
|
||||
canSelectTarget = 3;
|
||||
}
|
||||
else if (moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
|
||||
else if (IsSpreadMove(moveTarget, IGNORE_BATTLE_TYPE) || moveTarget == TARGET_OPPONENTS_FIELD)
|
||||
{
|
||||
TryShowAsTarget(gMultiUsePlayerCursor);
|
||||
TryShowAsTarget(BATTLE_PARTNER(gMultiUsePlayerCursor));
|
||||
if (moveTarget & MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
TryShowAsTarget(BATTLE_PARTNER(battler));
|
||||
canSelectTarget = 2;
|
||||
}
|
||||
|
|
@ -740,7 +760,7 @@ void HandleInputChooseMove(u32 battler)
|
|||
case 1:
|
||||
gBattlerControllerFuncs[battler] = HandleInputChooseTarget;
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
if (moveTarget == TARGET_USER || moveTarget == TARGET_USER_OR_ALLY)
|
||||
gMultiUsePlayerCursor = battler;
|
||||
else if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)))
|
||||
gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
|
|
@ -1996,8 +2016,8 @@ static void PlayerHandleChooseAction(u32 battler)
|
|||
StringCopy(gStringVar1, COMPOUND_STRING("Partner will use:\n"));
|
||||
u32 move = GetChosenMoveFromPosition(B_POSITION_PLAYER_RIGHT);
|
||||
StringAppend(gStringVar1, GetMoveName(move));
|
||||
u32 moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move);
|
||||
if (moveTarget == MOVE_TARGET_SELECTED)
|
||||
enum MoveTarget moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move);
|
||||
if (moveTarget == TARGET_SELECTED)
|
||||
{
|
||||
if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_LEFT)
|
||||
StringAppend(gStringVar1, COMPOUND_STRING(" -{UP_ARROW}"));
|
||||
|
|
@ -2008,15 +2028,15 @@ static void PlayerHandleChooseAction(u32 battler)
|
|||
else if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_RIGHT)
|
||||
StringAppend(gStringVar1, COMPOUND_STRING(" -{DOWN_ARROW}"));
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_BOTH)
|
||||
else if (moveTarget == TARGET_BOTH)
|
||||
{
|
||||
StringAppend(gStringVar1, COMPOUND_STRING(" {UP_ARROW}{UP_ARROW}"));
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
StringAppend(gStringVar1, COMPOUND_STRING(" {V_D_ARROW}{UP_ARROW}"));
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_ALL_BATTLERS)
|
||||
else if (moveTarget == TARGET_ALL_BATTLERS || moveTarget == TARGET_FIELD)
|
||||
{
|
||||
StringAppend(gStringVar1, COMPOUND_STRING(" {V_D_ARROW}{V_D_ARROW}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,9 +262,11 @@ static void PlayerPartnerHandleChooseMove(u32 battler)
|
|||
gBattlerTarget = gAiBattleData->chosenTarget[battler];
|
||||
u32 moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveIndex]);
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
if (moveTarget == TARGET_USER || moveTarget == TARGET_USER_OR_ALLY)
|
||||
{
|
||||
gBattlerTarget = battler;
|
||||
else if (moveTarget & MOVE_TARGET_BOTH)
|
||||
}
|
||||
else if (moveTarget == TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
if (gAbsentBattlerFlags & (1u << gBattlerTarget))
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler)
|
|||
#define minGroupNum var2
|
||||
#define selectedGroup percent
|
||||
#define selectedMoves var2
|
||||
#define moveTarget var1
|
||||
#define numMovesPerGroup var1
|
||||
#define numMultipleMoveGroups var2
|
||||
#define randSelectGroup var2
|
||||
|
|
@ -297,11 +296,11 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler)
|
|||
}
|
||||
}
|
||||
|
||||
moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveIndex]);
|
||||
enum MoveTarget moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveIndex]);
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
if (moveTarget == TARGET_USER || moveTarget == TARGET_USER_OR_ALLY)
|
||||
chosenMoveIndex |= (battler << 8);
|
||||
else if (moveTarget == MOVE_TARGET_SELECTED)
|
||||
else if (moveTarget == TARGET_SELECTED)
|
||||
chosenMoveIndex |= GetBattlePalaceTarget(battler);
|
||||
else
|
||||
chosenMoveIndex |= (GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(battler))) << 8);
|
||||
|
|
@ -322,22 +321,24 @@ static u8 GetBattlePalaceMoveGroup(u8 battler, u16 move)
|
|||
{
|
||||
switch (GetBattlerMoveTargetType(battler, move))
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_OPPONENT:
|
||||
case MOVE_TARGET_RANDOM:
|
||||
case MOVE_TARGET_BOTH:
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case MOVE_TARGET_ALL_BATTLERS:
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_OPPONENT:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
case TARGET_ALL_BATTLERS:
|
||||
case TARGET_FIELD:
|
||||
if (IsBattleMoveStatus(move))
|
||||
return PALACE_MOVE_GROUP_SUPPORT;
|
||||
else
|
||||
return PALACE_MOVE_GROUP_ATTACK;
|
||||
break;
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
case MOVE_TARGET_OPPONENTS_FIELD:
|
||||
case MOVE_TARGET_ALLY:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
case TARGET_ALLY:
|
||||
case TARGET_USER_OR_ALLY:
|
||||
return PALACE_MOVE_GROUP_SUPPORT;
|
||||
case MOVE_TARGET_USER:
|
||||
case TARGET_USER:
|
||||
return PALACE_MOVE_GROUP_DEFENSE;
|
||||
default:
|
||||
return PALACE_MOVE_GROUP_ATTACK;
|
||||
|
|
|
|||
|
|
@ -966,21 +966,21 @@ static void ValidateSavedBattlerCounts(void)
|
|||
static bool32 NoTargetPresent(u8 battler, u32 move)
|
||||
{
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
gBattlerTarget = GetBattleMoveTarget(move, NO_TARGET_OVERRIDE);
|
||||
gBattlerTarget = GetBattleMoveTarget(move, TARGET_NONE);
|
||||
|
||||
switch (GetBattlerMoveTargetType(battler, move))
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
case MOVE_TARGET_RANDOM:
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_RANDOM:
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
return TRUE;
|
||||
break;
|
||||
case MOVE_TARGET_BOTH:
|
||||
case TARGET_BOTH:
|
||||
if (!IsBattlerAlive(gBattlerTarget) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)))
|
||||
return TRUE;
|
||||
break;
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
if (!IsBattlerAlive(gBattlerTarget) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))
|
||||
return TRUE;
|
||||
break;
|
||||
|
|
@ -1230,7 +1230,7 @@ static void Cmd_attackcanceler(void)
|
|||
if (!bounceActive
|
||||
&& !gBattleStruct->bouncedMoveIsUsed
|
||||
&& isBounceable
|
||||
&& GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) == MOVE_TARGET_OPPONENTS_FIELD)
|
||||
&& GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) == TARGET_OPPONENTS_FIELD)
|
||||
{
|
||||
u32 partner = BATTLE_PARTNER(gBattlerTarget);
|
||||
|
||||
|
|
@ -1273,7 +1273,7 @@ static void Cmd_attackcanceler(void)
|
|||
gBattleStruct->bouncedMoveIsUsed = TRUE;
|
||||
}
|
||||
else if (IsDoubleBattle()
|
||||
&& GetBattlerMoveTargetType(battler, gCurrentMove) == MOVE_TARGET_OPPONENTS_FIELD
|
||||
&& GetBattlerMoveTargetType(battler, gCurrentMove) == TARGET_OPPONENTS_FIELD
|
||||
&& GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) == ABILITY_MAGIC_BOUNCE)
|
||||
{
|
||||
gBattlerTarget = battler = BATTLE_PARTNER(gBattlerTarget);
|
||||
|
|
@ -1466,7 +1466,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
|||
numMisses = 0,
|
||||
moveType = GetBattleMoveType(move),
|
||||
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
||||
bool32 calcSpreadMove = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(move);
|
||||
bool32 calcSpreadMove = IsSpreadMove(moveTarget, CHECK_BATTLE_TYPE) && !IsBattleMoveStatus(move);
|
||||
|
||||
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
|
|
@ -1626,7 +1626,7 @@ static void Cmd_damagecalc(void)
|
|||
ctx.randomFactor = TRUE;
|
||||
ctx.updateFlags = TRUE;
|
||||
|
||||
if (IsSpreadMove(moveTarget))
|
||||
if (IsSpreadMove(moveTarget, CHECK_BATTLE_TYPE))
|
||||
{
|
||||
u32 battlerDef;
|
||||
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
|
|
@ -1653,7 +1653,7 @@ static void Cmd_typecalc(void)
|
|||
{
|
||||
CMD_ARGS();
|
||||
|
||||
if (!IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove))) // Handled in CANCELER_MULTI_TARGET_MOVES for Spread Moves
|
||||
if (!IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), CHECK_BATTLE_TYPE)) // Handled in CANCELER_MULTI_TARGET_MOVES for Spread Moves
|
||||
{
|
||||
struct BattleContext ctx = {0};
|
||||
ctx.battlerAtk = gBattlerAttacker;
|
||||
|
|
@ -1684,7 +1684,7 @@ static void Cmd_adjustdamage(void)
|
|||
u32 affectionScore;
|
||||
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove);
|
||||
bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove);
|
||||
bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget, CHECK_BATTLE_TYPE) && !IsBattleMoveStatus(gCurrentMove);
|
||||
u32 enduredHit = 0;
|
||||
|
||||
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
|
|
@ -1934,7 +1934,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void)
|
|||
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget)
|
||||
|| (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && !(moveTarget & MOVE_TARGET_FOES_AND_ALLY))
|
||||
|| (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && moveTarget != TARGET_FOES_AND_ALLY)
|
||||
|| gBattleStruct->noResultString[battlerDef] == WILL_FAIL)
|
||||
continue;
|
||||
|
||||
|
|
@ -1946,7 +1946,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void)
|
|||
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget)
|
||||
|| (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && !(moveTarget & MOVE_TARGET_FOES_AND_ALLY))
|
||||
|| (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && moveTarget != TARGET_FOES_AND_ALLY)
|
||||
|| gBattleStruct->noResultString[battlerDef] == WILL_FAIL)
|
||||
continue;
|
||||
|
||||
|
|
@ -2003,17 +2003,19 @@ static void Cmd_attackanimation(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((moveTarget & MOVE_TARGET_BOTH
|
||||
|| moveTarget & MOVE_TARGET_FOES_AND_ALLY
|
||||
|| moveTarget & MOVE_TARGET_DEPENDS)
|
||||
&& gBattleScripting.animTargetsHit)
|
||||
if (gBattleScripting.animTargetsHit)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
if (moveTarget == TARGET_BOTH
|
||||
|| moveTarget == TARGET_FOES_AND_ALLY
|
||||
|| moveTarget == TARGET_DEPENDS)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// handle special move animations
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_EXPANDING_FORCE && moveTarget & MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, BATTLE_OPPOSITE(gBattlerAttacker) > 1))
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_EXPANDING_FORCE && moveTarget == TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, BATTLE_OPPOSITE(gBattlerAttacker) > 1))
|
||||
gBattleScripting.animTurn = 1;
|
||||
|
||||
if (!(moveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
|
|
@ -5401,7 +5403,7 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent)
|
|||
|
||||
if (!(excludeCurrent && battler == gBattlerTarget)
|
||||
&& !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler]
|
||||
&& (!IsBattlerAlly(battler, gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||
&& (!IsBattlerAlly(battler, gBattlerAttacker) || moveTarget == TARGET_FOES_AND_ALLY))
|
||||
break;
|
||||
}
|
||||
return battler;
|
||||
|
|
@ -6344,10 +6346,8 @@ static void Cmd_moveend(void)
|
|||
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE;
|
||||
if (!gBattleStruct->unableToUseMove
|
||||
&& IsDoubleBattle()
|
||||
&& !gProtectStructs[gBattlerAttacker].chargingTurn
|
||||
&& (moveTarget == MOVE_TARGET_BOTH
|
||||
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||
&& IsSpreadMove(moveTarget, CHECK_BATTLE_TYPE)
|
||||
&& !gProtectStructs[gBattlerAttacker].chargingTurn)
|
||||
{
|
||||
u32 nextTarget = GetNextTarget(moveTarget, FALSE);
|
||||
|
||||
|
|
@ -9346,8 +9346,13 @@ static void Cmd_jumpifnexttargetvalid(void)
|
|||
|
||||
for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER))
|
||||
continue;
|
||||
if (gBattlerTarget == gBattlerAttacker)
|
||||
{
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
if (target != TARGET_USER && target != TARGET_ALL_BATTLERS)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsBattlerAlive(gBattlerTarget))
|
||||
break;
|
||||
}
|
||||
|
|
@ -11519,7 +11524,7 @@ static void Cmd_trysetperishsong(void)
|
|||
{
|
||||
CMD_ARGS(const u8 *failInstr);
|
||||
|
||||
s32 i;
|
||||
s32 i = 0;
|
||||
s32 notAffectedCount = 0;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
|
|
@ -11942,7 +11947,7 @@ static void Cmd_selectfirstvalidtarget(void)
|
|||
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER))
|
||||
if (gBattlerTarget == gBattlerAttacker && GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) != TARGET_USER)
|
||||
continue;
|
||||
if (IsBattlerAlive(gBattlerTarget))
|
||||
break;
|
||||
|
|
@ -14160,12 +14165,12 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler)
|
|||
switch (GetBattlerMoveTargetType(battler, move))
|
||||
{
|
||||
// Both foes are alive, spread move strikes once
|
||||
case MOVE_TARGET_BOTH:
|
||||
case TARGET_BOTH:
|
||||
if (CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) >= 2)
|
||||
return FALSE;
|
||||
break;
|
||||
// Either both foes or one foe and its ally are alive; spread move strikes once
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker) >= 2)
|
||||
return FALSE;
|
||||
break;
|
||||
|
|
@ -16307,7 +16312,7 @@ void BS_IsRunningImpossible(void)
|
|||
void BS_GetMoveTarget(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattlerTarget = GetBattleMoveTarget(gCurrentMove, TARGET_NONE);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -816,7 +816,7 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3)
|
|||
baseFromEffect += 3;
|
||||
break;
|
||||
case EFFECT_CONFUSE:
|
||||
if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (GetBattlerMoveTargetType(gBattlerAttacker, move) == TARGET_FOES_AND_ALLY)
|
||||
baseFromEffect += 2;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -397,14 +397,14 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|
|||
bool32 HandleMoveTargetRedirection(void)
|
||||
{
|
||||
u32 redirectorOrderNum = MAX_BATTLERS_COUNT;
|
||||
u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
enum MoveTarget moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
enum Type moveType = GetBattleMoveType(gCurrentMove);
|
||||
enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove);
|
||||
u32 side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker));
|
||||
enum Ability ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]);
|
||||
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove)
|
||||
&& moveTarget == MOVE_TARGET_SELECTED
|
||||
&& moveTarget == TARGET_SELECTED
|
||||
&& !IsBattlerAlly(gBattlerAttacker, gSideTimers[side].followmeTarget))
|
||||
{
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = gSideTimers[side].followmeTarget; // follow me moxie fix
|
||||
|
|
@ -412,7 +412,7 @@ bool32 HandleMoveTargetRedirection(void)
|
|||
}
|
||||
else if (IsDoubleBattle()
|
||||
&& gSideTimers[side].followmeTimer == 0
|
||||
&& (!IsBattleMoveStatus(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS))
|
||||
&& (!IsBattleMoveStatus(gCurrentMove) || (moveTarget != TARGET_USER && moveTarget != TARGET_ALL_BATTLERS && moveTarget != TARGET_FIELD))
|
||||
&& ((ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|
||||
|| (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
|
||||
{
|
||||
|
|
@ -450,6 +450,18 @@ bool32 HandleMoveTargetRedirection(void)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static bool32 WasOriginalTargetAlly(enum MoveTarget target)
|
||||
{
|
||||
if (!gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch)
|
||||
return FALSE;
|
||||
|
||||
if ((target == TARGET_ALLY || target == TARGET_USER_OR_ALLY) && gBattlerAttacker == gBattlerTarget)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Functions
|
||||
void HandleAction_UseMove(void)
|
||||
{
|
||||
|
|
@ -471,7 +483,7 @@ void HandleAction_UseMove(void)
|
|||
{
|
||||
gProtectStructs[gBattlerAttacker].noValidMoves = FALSE;
|
||||
gCurrentMove = gChosenMove = MOVE_STRUGGLE;
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, TARGET_NONE);
|
||||
}
|
||||
else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gBattleMons[gBattlerAttacker].volatiles.rechargeTimer > 0)
|
||||
{
|
||||
|
|
@ -484,7 +496,7 @@ void HandleAction_UseMove(void)
|
|||
gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].volatiles.encoredMove;
|
||||
gCurrMovePos = gChosenMovePos = gBattleMons[gBattlerAttacker].volatiles.encoredMovePos;
|
||||
if (GetConfig(CONFIG_ENCORE_TARGET) < GEN_5)
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, TARGET_NONE);
|
||||
}
|
||||
// check if the encored move wasn't overwritten
|
||||
else if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gBattleMons[gBattlerAttacker].volatiles.encoredMove != MOVE_NONE
|
||||
|
|
@ -495,12 +507,12 @@ void HandleAction_UseMove(void)
|
|||
gBattleMons[gBattlerAttacker].volatiles.encoredMove = MOVE_NONE;
|
||||
gBattleMons[gBattlerAttacker].volatiles.encoredMovePos = 0;
|
||||
gBattleMons[gBattlerAttacker].volatiles.encoreTimer = 0;
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, TARGET_NONE);
|
||||
}
|
||||
else if (gBattleMons[gBattlerAttacker].moves[gCurrMovePos] != gChosenMoveByBattler[gBattlerAttacker])
|
||||
{
|
||||
gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE);
|
||||
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(gCurrentMove, TARGET_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -540,7 +552,7 @@ void HandleAction_UseMove(void)
|
|||
|
||||
if (!HandleMoveTargetRedirection())
|
||||
{
|
||||
if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM)
|
||||
if (IsDoubleBattle() && moveTarget == TARGET_RANDOM)
|
||||
{
|
||||
gBattlerTarget = SetRandomTarget(gBattlerAttacker);
|
||||
if (gAbsentBattlerFlags & (1u << gBattlerTarget)
|
||||
|
|
@ -549,14 +561,14 @@ void HandleAction_UseMove(void)
|
|||
gBattlerTarget = GetPartnerBattler(gBattlerTarget);
|
||||
}
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_ALLY)
|
||||
else if (moveTarget == TARGET_ALLY)
|
||||
{
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)) && !gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch)
|
||||
gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker);
|
||||
else
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
}
|
||||
else if (IsDoubleBattle() && moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (IsDoubleBattle() && moveTarget == TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
|
|
@ -566,7 +578,7 @@ void HandleAction_UseMove(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_USER)
|
||||
else if (moveTarget == TARGET_USER)
|
||||
{
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
}
|
||||
|
|
@ -574,7 +586,7 @@ void HandleAction_UseMove(void)
|
|||
{
|
||||
gBattlerTarget = gBattleStruct->moveTarget[gBattlerAttacker];
|
||||
if (!IsBattlerAlive(gBattlerTarget)
|
||||
&& moveTarget != MOVE_TARGET_OPPONENTS_FIELD
|
||||
&& moveTarget != TARGET_OPPONENTS_FIELD
|
||||
&& IsDoubleBattle()
|
||||
&& (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)))
|
||||
{
|
||||
|
|
@ -607,9 +619,7 @@ void HandleAction_UseMove(void)
|
|||
{
|
||||
gBattlescriptCurrInstr = BattleScript_FailedFromAtkCanceler;
|
||||
}
|
||||
// If originally targetting an ally but now targetting user due to Ally Switch
|
||||
else if (moveTarget & MOVE_TARGET_ALLY && gBattlerAttacker == gBattlerTarget
|
||||
&& gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch)
|
||||
else if (WasOriginalTargetAlly(moveTarget))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_FailedFromAtkCanceler;
|
||||
}
|
||||
|
|
@ -2109,7 +2119,7 @@ static enum MoveCanceler CancelerObedience(struct BattleContext *ctx)
|
|||
case DISOBEYS_RANDOM_MOVE:
|
||||
gCurrentMove = gCalledMove = gBattleMons[ctx->battlerAtk].moves[gCurrMovePos];
|
||||
BattleScriptCall(BattleScript_IgnoresAndUsesRandomMove);
|
||||
gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
|
||||
gBattlerTarget = GetBattleMoveTarget(gCalledMove, TARGET_NONE);
|
||||
return MOVE_STEP_BREAK;
|
||||
}
|
||||
}
|
||||
|
|
@ -2345,7 +2355,7 @@ static enum MoveCanceler CancelerBide(struct BattleContext *ctx)
|
|||
gCurrentMove = MOVE_BIDE;
|
||||
gBattlerTarget = gBideTarget[ctx->battlerAtk];
|
||||
if (gAbsentBattlerFlags & (1u << ctx->battlerDef))
|
||||
gBattlerTarget = GetBattleMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1);
|
||||
gBattlerTarget = GetBattleMoveTarget(MOVE_BIDE, TARGET_NONE);
|
||||
gBattlescriptCurrInstr = BattleScript_BideAttack;
|
||||
return MOVE_STEP_BREAK; // Jumps to a different script but no failure
|
||||
}
|
||||
|
|
@ -2516,9 +2526,9 @@ static enum MoveCanceler CancelerPPDeduction(struct BattleContext *ctx)
|
|||
if (gBattleStruct->submoveAnnouncement == SUBMOVE_SUCCESS)
|
||||
movePosition = gChosenMovePos;
|
||||
|
||||
if (moveTarget == MOVE_TARGET_BOTH
|
||||
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY
|
||||
|| moveTarget == MOVE_TARGET_ALL_BATTLERS
|
||||
if (IsSpreadMove(moveTarget, IGNORE_BATTLE_TYPE)
|
||||
|| moveTarget == TARGET_ALL_BATTLERS
|
||||
|| moveTarget == TARGET_FIELD
|
||||
|| MoveForcesPressure(ctx->move))
|
||||
{
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
|
|
@ -2527,7 +2537,7 @@ static enum MoveCanceler CancelerPPDeduction(struct BattleContext *ctx)
|
|||
ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE);
|
||||
}
|
||||
}
|
||||
else if (moveTarget != MOVE_TARGET_OPPONENTS_FIELD)
|
||||
else if (moveTarget != TARGET_OPPONENTS_FIELD)
|
||||
{
|
||||
if (ctx->battlerAtk != ctx->battlerDef && ctx->abilityDef == ABILITY_PRESSURE)
|
||||
ppToDeduct++;
|
||||
|
|
@ -2570,7 +2580,7 @@ static enum MoveCanceler CancelerPPDeduction(struct BattleContext *ctx)
|
|||
else
|
||||
{
|
||||
gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT;
|
||||
gBattlerTarget = GetBattleMoveTarget(ctx->move, NO_TARGET_OVERRIDE);
|
||||
gBattlerTarget = GetBattleMoveTarget(ctx->move, TARGET_NONE);
|
||||
gBattleScripting.animTurn = 0;
|
||||
gBattleScripting.animTargetsHit = 0;
|
||||
|
||||
|
|
@ -2925,7 +2935,7 @@ static enum MoveCanceler CancelerMultiTargetMoves(struct BattleContext *ctx)
|
|||
u32 moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->move);
|
||||
enum Ability abilityAtk = ctx->abilityAtk;
|
||||
|
||||
if (IsSpreadMove(moveTarget))
|
||||
if (IsSpreadMove(moveTarget, CHECK_BATTLE_TYPE))
|
||||
{
|
||||
for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
{
|
||||
|
|
@ -2937,7 +2947,7 @@ static enum MoveCanceler CancelerMultiTargetMoves(struct BattleContext *ctx)
|
|||
if (ctx->battlerAtk == battlerDef
|
||||
|| !IsBattlerAlive(battlerDef)
|
||||
|| (GetMoveEffect(ctx->move) == EFFECT_SYNCHRONOISE && !DoBattlersShareType(ctx->battlerAtk, battlerDef))
|
||||
|| (moveTarget == MOVE_TARGET_BOTH && ctx->battlerAtk == BATTLE_PARTNER(battlerDef))
|
||||
|| (moveTarget == TARGET_BOTH && ctx->battlerAtk == BATTLE_PARTNER(battlerDef))
|
||||
|| IsBattlerProtected(ctx->battlerAtk, battlerDef, ctx->move)) // Missing Invulnerable check
|
||||
{
|
||||
gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT;
|
||||
|
|
@ -2959,7 +2969,7 @@ static enum MoveCanceler CancelerMultiTargetMoves(struct BattleContext *ctx)
|
|||
gBattleStruct->noResultString[battlerDef] = CAN_DAMAGE;
|
||||
}
|
||||
}
|
||||
if (moveTarget == MOVE_TARGET_BOTH)
|
||||
if (moveTarget == TARGET_BOTH)
|
||||
gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, ctx->battlerAtk);
|
||||
else
|
||||
gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, ctx->battlerAtk);
|
||||
|
|
@ -3418,8 +3428,12 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityA
|
|||
switch (abilityDef)
|
||||
{
|
||||
case ABILITY_SOUNDPROOF:
|
||||
if (IsSoundMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER))
|
||||
battleScriptBlocksMove = BattleScript_SoundproofProtected;
|
||||
if (IsSoundMove(move))
|
||||
{
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
if (target != TARGET_USER && target != TARGET_ALL_BATTLERS)
|
||||
battleScriptBlocksMove = BattleScript_SoundproofProtected;
|
||||
}
|
||||
break;
|
||||
case ABILITY_BULLETPROOF:
|
||||
if (IsBallisticMove(move))
|
||||
|
|
@ -3428,7 +3442,11 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityA
|
|||
case ABILITY_GOOD_AS_GOLD:
|
||||
if (IsBattleMoveStatus(move))
|
||||
{
|
||||
if (!(GetBattlerMoveTargetType(battlerAtk, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_ALL_BATTLERS)))
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
if (target != TARGET_OPPONENTS_FIELD
|
||||
&& target != TARGET_ALL_BATTLERS
|
||||
&& target != TARGET_FIELD
|
||||
&& target != TARGET_USER)
|
||||
battleScriptBlocksMove = BattleScript_GoodAsGoldActivates;
|
||||
}
|
||||
break;
|
||||
|
|
@ -3452,20 +3470,21 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityA
|
|||
&& BlocksPrankster(move, battlerAtk, battlerDef, TRUE)
|
||||
&& !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove)))
|
||||
{
|
||||
if (option == RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move)))
|
||||
if (option == RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move), CHECK_BATTLE_TYPE))
|
||||
CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||
battleScriptBlocksMove = BattleScript_DoesntAffectTargetAtkString;
|
||||
}
|
||||
else if (IsPsychicTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), gFieldStatuses) // Not an ability but similar conditions
|
||||
&& !IsBattlerAlly(battlerAtk, battlerDef)
|
||||
&& GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS
|
||||
&& GetMoveTarget(move) != MOVE_TARGET_OPPONENTS_FIELD)
|
||||
&& GetMoveTarget(move) != TARGET_ALL_BATTLERS
|
||||
&& GetMoveTarget(move) != TARGET_FIELD
|
||||
&& GetMoveTarget(move) != TARGET_OPPONENTS_FIELD)
|
||||
{
|
||||
battleScriptBlocksMove = BattleScript_MoveUsedPsychicTerrainPrevents;
|
||||
if (option == RUN_SCRIPT)
|
||||
{
|
||||
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
|
||||
if (!IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move)))
|
||||
if (!IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move), CHECK_BATTLE_TYPE))
|
||||
CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents;
|
||||
return TRUE; // Early return since we don't want to set remaining values
|
||||
|
|
@ -3494,6 +3513,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
|||
const u8 *battleScript = NULL;
|
||||
enum Stat statId = 0;
|
||||
u32 statAmount = 1;
|
||||
enum MoveTarget target = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
|
||||
switch (abilityDef)
|
||||
{
|
||||
|
|
@ -3501,7 +3521,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
|||
effect = MOVE_ABSORBED_BY_NO_ABILITY;
|
||||
break;
|
||||
case ABILITY_VOLT_ABSORB:
|
||||
if (moveType == TYPE_ELECTRIC && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_ALL_BATTLERS)
|
||||
if (moveType == TYPE_ELECTRIC && target != TARGET_ALL_BATTLERS && target != TARGET_FIELD)
|
||||
effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY;
|
||||
break;
|
||||
case ABILITY_WATER_ABSORB:
|
||||
|
|
@ -3514,14 +3534,14 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
|||
effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY;
|
||||
break;
|
||||
case ABILITY_MOTOR_DRIVE:
|
||||
if (moveType == TYPE_ELECTRIC && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_ALL_BATTLERS)
|
||||
if (moveType == TYPE_ELECTRIC && target != TARGET_ALL_BATTLERS && target != TARGET_FIELD)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPEED;
|
||||
}
|
||||
break;
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_ALL_BATTLERS)
|
||||
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && target != TARGET_ALL_BATTLERS)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPATK;
|
||||
|
|
@ -3550,7 +3570,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
|||
}
|
||||
break;
|
||||
case ABILITY_WIND_RIDER:
|
||||
if (IsWindMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER))
|
||||
if (IsWindMove(move) && target != TARGET_USER)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_ATK;
|
||||
|
|
@ -6519,21 +6539,19 @@ u32 SetRandomTarget(u32 battlerAtk)
|
|||
return target;
|
||||
}
|
||||
|
||||
u32 GetBattleMoveTarget(u16 move, u8 setTarget)
|
||||
u32 GetBattleMoveTarget(u32 move, enum MoveTarget moveTarget)
|
||||
{
|
||||
u8 targetBattler = 0;
|
||||
u32 moveTarget, side;
|
||||
u32 targetBattler = 0;
|
||||
u32 side;
|
||||
enum Type moveType = GetBattleMoveType(move);
|
||||
|
||||
if (setTarget != NO_TARGET_OVERRIDE)
|
||||
moveTarget = setTarget - 1;
|
||||
else
|
||||
if (moveTarget == TARGET_NONE)
|
||||
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
||||
|
||||
switch (moveTarget)
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_OPPONENT:
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_OPPONENT:
|
||||
side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker));
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, move))
|
||||
{
|
||||
|
|
@ -6574,30 +6592,30 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
case MOVE_TARGET_BOTH:
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_BOTH:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
targetBattler = GetOpposingSideBattler(gBattlerAttacker);
|
||||
if (IsDoubleBattle() && !IsBattlerAlive(targetBattler))
|
||||
targetBattler ^= BIT_FLANK;
|
||||
break;
|
||||
case MOVE_TARGET_OPPONENTS_FIELD:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
targetBattler = GetOpposingSideBattler(gBattlerAttacker);
|
||||
break;
|
||||
case MOVE_TARGET_RANDOM:
|
||||
case TARGET_RANDOM:
|
||||
side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker));
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, move))
|
||||
targetBattler = gSideTimers[side].followmeTarget;
|
||||
else if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM)
|
||||
else if (IsDoubleBattle())
|
||||
targetBattler = SetRandomTarget(gBattlerAttacker);
|
||||
else
|
||||
targetBattler = GetOpposingSideBattler(gBattlerAttacker);
|
||||
break;
|
||||
case MOVE_TARGET_USER:
|
||||
case TARGET_USER:
|
||||
default:
|
||||
targetBattler = gBattlerAttacker;
|
||||
break;
|
||||
case MOVE_TARGET_ALLY:
|
||||
case TARGET_ALLY:
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))
|
||||
targetBattler = BATTLE_PARTNER(gBattlerAttacker);
|
||||
else
|
||||
|
|
@ -6817,7 +6835,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
isProtected = TRUE;
|
||||
else if (MoveIgnoresProtect(move))
|
||||
isProtected = FALSE;
|
||||
else if (IsSideProtected(battlerDef, PROTECT_WIDE_GUARD) && IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move)))
|
||||
else if (IsSideProtected(battlerDef, PROTECT_WIDE_GUARD) && IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move), CHECK_BATTLE_TYPE))
|
||||
isProtected = TRUE;
|
||||
else if (gProtectStructs[battlerDef].protected == PROTECT_NORMAL)
|
||||
isProtected = TRUE;
|
||||
|
|
@ -7002,21 +7020,21 @@ u32 GetMoveTargetCount(struct BattleContext *ctx)
|
|||
|
||||
switch (GetBattlerMoveTargetType(battlerAtk, move))
|
||||
{
|
||||
case MOVE_TARGET_BOTH:
|
||||
case TARGET_BOTH:
|
||||
return !(gAbsentBattlerFlags & (1u << battlerDef))
|
||||
+ !(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(battlerDef)));
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
return !(gAbsentBattlerFlags & (1u << battlerDef))
|
||||
+ !(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(battlerDef)))
|
||||
+ !(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(battlerAtk)));
|
||||
case MOVE_TARGET_OPPONENTS_FIELD:
|
||||
case TARGET_OPPONENTS_FIELD:
|
||||
return 1;
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_RANDOM:
|
||||
case MOVE_TARGET_OPPONENT:
|
||||
case TARGET_DEPENDS:
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_OPPONENT:
|
||||
return IsBattlerAlive(battlerDef);
|
||||
case MOVE_TARGET_USER:
|
||||
case TARGET_USER:
|
||||
return IsBattlerAlive(battlerAtk);
|
||||
default:
|
||||
return 0;
|
||||
|
|
@ -10296,7 +10314,9 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch
|
|||
return FALSE;
|
||||
if (IsBattlerAlly(battlerPrankster, battlerDef))
|
||||
return FALSE;
|
||||
if (checkTarget && (GetBattlerMoveTargetType(battlerPrankster, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)))
|
||||
if (checkTarget && GetBattlerMoveTargetType(battlerPrankster, move) == TARGET_DEPENDS)
|
||||
return FALSE;
|
||||
if (checkTarget && GetBattlerMoveTargetType(battlerPrankster, move) == TARGET_OPPONENTS_FIELD)
|
||||
return FALSE;
|
||||
if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK))
|
||||
return FALSE;
|
||||
|
|
@ -10342,11 +10362,11 @@ u32 GetBattlerMoveTargetType(u32 battler, u32 move)
|
|||
{
|
||||
enum BattleMoveEffects effect = GetMoveEffect(move);
|
||||
if (effect == EFFECT_CURSE && !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST))
|
||||
return MOVE_TARGET_USER;
|
||||
return TARGET_USER;
|
||||
if (effect == EFFECT_EXPANDING_FORCE && IsPsychicTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), gFieldStatuses))
|
||||
return MOVE_TARGET_BOTH;
|
||||
return TARGET_BOTH;
|
||||
if (effect == EFFECT_TERA_STARSTORM && gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
|
||||
return MOVE_TARGET_BOTH;
|
||||
return TARGET_BOTH;
|
||||
|
||||
return GetMoveTarget(move);
|
||||
}
|
||||
|
|
@ -10877,7 +10897,7 @@ void UpdateStallMons(void)
|
|||
{
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || GetMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_STATUS)
|
||||
return;
|
||||
if (!IsDoubleBattle() || GetMoveTarget(gCurrentMove) == MOVE_TARGET_SELECTED)
|
||||
if (!IsDoubleBattle() || GetMoveTarget(gCurrentMove) == TARGET_SELECTED)
|
||||
{
|
||||
enum Type moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now
|
||||
enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||
|
|
|
|||
|
|
@ -5430,14 +5430,14 @@ static void SetMoveTargetPosition(u16 move)
|
|||
{
|
||||
switch (GetBattlerMoveTargetType(gBattlerAttacker, move))
|
||||
{
|
||||
case MOVE_TARGET_USER:
|
||||
case TARGET_USER:
|
||||
gBattlerTarget = B_POSITION_PLAYER_RIGHT;
|
||||
break;
|
||||
case MOVE_TARGET_OPPONENT:
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_RANDOM:
|
||||
case MOVE_TARGET_BOTH:
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
case TARGET_OPPONENT:
|
||||
case TARGET_SELECTED:
|
||||
case TARGET_RANDOM:
|
||||
case TARGET_BOTH:
|
||||
case TARGET_FOES_AND_ALLY:
|
||||
default:
|
||||
gBattlerTarget = B_POSITION_OPPONENT_RIGHT;
|
||||
break;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -175,7 +175,7 @@ DOUBLE_BATTLE_TEST("Commander prevents Red Card from working while Commander is
|
|||
DOUBLE_BATTLE_TEST("Commander Tatsugiri is not damaged by a double target move if Dondozo faints")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_DONDOZO) { HP(1); };
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
|
|
@ -308,7 +308,7 @@ DOUBLE_BATTLE_TEST("Commander Tatsugiri is still affected by Haze while controll
|
|||
DOUBLE_BATTLE_TEST("Commander Attacker is kept (Dondozo Left Slot)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
PLAYER(SPECIES_DONDOZO);
|
||||
|
|
@ -331,7 +331,7 @@ DOUBLE_BATTLE_TEST("Commander Attacker is kept (Dondozo Left Slot)")
|
|||
DOUBLE_BATTLE_TEST("Commander Attacker is kept (Dondozo Right Slot)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_DONDOZO);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ DOUBLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves and prints th
|
|||
GIVEN {
|
||||
ASSUME(!IsBattleMoveStatus(MOVE_SURF));
|
||||
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB); {Speed(5);}}
|
||||
PLAYER(SPECIES_WOBBUFFET) {Speed(5);}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Speed(10);}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ SINGLE_BATTLE_TEST("Good as Gold doesn't protect from moves that target the fiel
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveCategory(MOVE_STEALTH_ROCK) == DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveTarget(MOVE_STEALTH_ROCK) == MOVE_TARGET_OPPONENTS_FIELD);
|
||||
ASSUME(GetMoveTarget(MOVE_STEALTH_ROCK) == TARGET_OPPONENTS_FIELD);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GHOLDENGO) { Ability(ABILITY_GOOD_AS_GOLD); }
|
||||
} WHEN {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ DOUBLE_BATTLE_TEST("Grim Neigh raises Sp. Attack by one stage after directly cau
|
|||
PARAMETRIZE { species = SPECIES_SPECTRIER; ability = ABILITY_GRIM_NEIGH; abilityPopUp = ABILITY_GRIM_NEIGH; }
|
||||
PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(species) { Ability(ability); }
|
||||
PLAYER(SPECIES_SNORUNT) { HP(1); }
|
||||
OPPONENT(SPECIES_GLALIE) { HP(1); }
|
||||
|
|
@ -78,7 +78,7 @@ DOUBLE_BATTLE_TEST("Grim Neigh does not increase damage done by the same move th
|
|||
PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; abilityPopUp = ABILITY_GRIM_NEIGH; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(species) { Ability(ability); }
|
||||
PLAYER(SPECIES_ABRA) { HP(1); }
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting both foes at two foe
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_LEER) == EFFECT_DEFENSE_DOWN);
|
||||
ASSUME(GetMoveTarget(MOVE_LEER) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_LEER) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_ABRA);
|
||||
PLAYER(SPECIES_KADABRA);
|
||||
OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); }
|
||||
|
|
@ -95,7 +95,7 @@ DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting foes field")
|
|||
battlerTwo = SPECIES_ESPEON; abilityBattlerTwo = ABILITY_MAGIC_BOUNCE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_STEALTH_ROCK) == MOVE_TARGET_OPPONENTS_FIELD);
|
||||
ASSUME(GetMoveTarget(MOVE_STEALTH_ROCK) == TARGET_OPPONENTS_FIELD);
|
||||
PLAYER(SPECIES_ABRA);
|
||||
PLAYER(SPECIES_KADABRA);
|
||||
OPPONENT(battlerOne) { Ability(abilityBattlerOne); }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after direct
|
|||
PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; }
|
||||
PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(species) { Ability(ability); }
|
||||
PLAYER(SPECIES_SNORUNT) { HP(1); }
|
||||
OPPONENT(SPECIES_GLALIE) { HP(1); }
|
||||
|
|
@ -121,7 +121,7 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not increase damage done by the sa
|
|||
PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(species) { Ability(ability); }
|
||||
PLAYER(SPECIES_ABRA) { HP(1); }
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ DOUBLE_BATTLE_TEST("Neutralizing Gas prevents ally's switch-in ability from acti
|
|||
DOUBLE_BATTLE_TEST("Neutralizing Gas ignores all battlers' ability effects")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
|
||||
OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_WATER_ABSORB); }
|
||||
|
|
@ -357,7 +357,7 @@ SINGLE_BATTLE_TEST("Neutralizing Gas only displays exiting message for the last
|
|||
DOUBLE_BATTLE_TEST("Neutralizing Gas is active for the duration of a Spread Move even if Neutralizing Gas is no longer on the field")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_ORIGIN_PULSE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_ORIGIN_PULSE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WEEZING) { HP(1); Ability(ABILITY_NEUTRALIZING_GAS); }
|
||||
PLAYER(SPECIES_GOLEM) { Ability(ABILITY_STURDY); }
|
||||
OPPONENT(SPECIES_BASCULEGION) { Ability(ABILITY_MOLD_BREAKER); }
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ SINGLE_BATTLE_TEST("Parental Bond converts multi-target moves into a two-strike
|
|||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveStrikeCount(MOVE_EARTHQUAKE) < 2);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveStrikeCount(MOVE_ICY_WIND) < 2);
|
||||
ASSUME(GetMoveTarget(MOVE_ICY_WIND) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_ICY_WIND) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
|
|
@ -79,7 +79,7 @@ DOUBLE_BATTLE_TEST("Parental Bond does not convert multi-target moves into a two
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveStrikeCount(MOVE_EARTHQUAKE) < 2);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
|
||||
PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); }
|
||||
PLAYER(SPECIES_PIDGEY);
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ SINGLE_BATTLE_TEST("Prankster is blocked by Quick Guard in Gen5+")
|
|||
DOUBLE_BATTLE_TEST("Prankster-affected moves that target all Pokémon are successful regardless of the presence of Dark-type Pokémon")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_CAPTIVATE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_CAPTIVATE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_ILLUMISE) { Ability(ABILITY_PRANKSTER); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_UMBREON);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints th
|
|||
GIVEN {
|
||||
ASSUME(!IsBattleMoveStatus(MOVE_ERUPTION));
|
||||
ASSUME(GetMoveType(MOVE_ERUPTION) == TYPE_FIRE);
|
||||
ASSUME(GetMoveTarget(MOVE_ERUPTION) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_ERUPTION) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB); {Speed(5);}}
|
||||
PLAYER(SPECIES_WOBBUFFET) {Speed(5);}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Speed(10);}
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ DOUBLE_BATTLE_TEST("Multi-target moves hit correct battlers after Seed Sower is
|
|||
}
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_ARBOLIVA) { Ability(abilities[B_POSITION_PLAYER_LEFT]); }
|
||||
PLAYER(SPECIES_ARBOLIVA) { Ability(abilities[B_POSITION_PLAYER_RIGHT]); }
|
||||
OPPONENT(SPECIES_ARBOLIVA) { Ability(abilities[B_POSITION_OPPONENT_LEFT]); }
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ DOUBLE_BATTLE_TEST("Stamina activates correctly for every battler with the abili
|
|||
PARAMETRIZE {abilityLeft = ABILITY_STAMINA, abilityRight = ABILITY_STAMINA; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Speed(20); }
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ DOUBLE_BATTLE_TEST("Toxic Chain can inflict bad poison on both foes")
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveCategory(MOVE_RAZOR_LEAF) != DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveTarget(MOVE_RAZOR_LEAF) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_RAZOR_LEAF) == TARGET_BOTH);
|
||||
ASSUME(GetMovePower(MOVE_RAZOR_LEAF) > 0);
|
||||
PLAYER(SPECIES_OKIDOGI) { Ability(ABILITY_TOXIC_CHAIN); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ ASSUMPTIONS
|
|||
ASSUME(!IsBattleMoveStatus(MOVE_SCRATCH));
|
||||
ASSUME(!IsWindMove(MOVE_SCRATCH));
|
||||
ASSUME(!IsBattleMoveStatus(MOVE_AIR_CUTTER));
|
||||
ASSUME(GetMoveTarget(MOVE_AIR_CUTTER) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_AIR_CUTTER) == TARGET_BOTH);
|
||||
ASSUME(IsWindMove(MOVE_AIR_CUTTER));
|
||||
ASSUME(!IsBattleMoveStatus(MOVE_PETAL_BLIZZARD));
|
||||
ASSUME(GetMoveTarget(MOVE_PETAL_BLIZZARD) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_PETAL_BLIZZARD) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(IsWindMove(MOVE_PETAL_BLIZZARD));
|
||||
ASSUME(!IsWindMove(MOVE_SCRATCH));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon only consider their own status moves whe
|
|||
|
||||
AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use stat boosting moves")
|
||||
{
|
||||
// Moves defined by MOVE_TARGET_USER (with exceptions?)
|
||||
// Moves defined by TARGET_USER (with exceptions?)
|
||||
u32 j, heldItem = ITEM_NONE;
|
||||
enum Ability ability = ABILITY_NONE;
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use stat boosting moves")
|
|||
}
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SWORDS_DANCE) == MOVE_TARGET_USER);
|
||||
ASSUME(GetMoveTarget(MOVE_SWORDS_DANCE) == TARGET_USER);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_RHYDON)
|
||||
OPPONENT(SPECIES_LOPUNNY) { Moves(MOVE_SWORDS_DANCE, MOVE_SCRATCH); Item(heldItem); Ability(ability); }
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ AI_DOUBLE_BATTLE_TEST("Heal Bell and Jungle Healing skip curing a partner that b
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will not choose Earthquake if it damages the partner without a positive effect")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
|
||||
u32 species;
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ AI_DOUBLE_BATTLE_TEST("AI will not choose Earthquake if it damages the partner w
|
|||
PARAMETRIZE { species = SPECIES_CHIKORITA; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
|
@ -192,10 +192,10 @@ AI_DOUBLE_BATTLE_TEST("AI will not choose Earthquake if it damages the partner w
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI recognizes its ally's Telepathy")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
|
@ -208,7 +208,7 @@ AI_DOUBLE_BATTLE_TEST("AI recognizes its ally's Telepathy")
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will choose Bulldoze if it triggers its ally's ability but will not KO the ally needlessly")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_BULLDOZE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_BULLDOZE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_BULLDOZE) == TYPE_GROUND);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_BULLDOZE, MOVE_EFFECT_SPD_MINUS_1));
|
||||
|
||||
|
|
@ -263,11 +263,11 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Beat Up on an ally with Justified if it wi
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if partner is not alive")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
|
@ -281,7 +281,7 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if partner is not alive")
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills one opposing mon and does not kill the partner needlessly")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
|
||||
u32 currentHP;
|
||||
|
|
@ -289,7 +289,7 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills one opposing mon an
|
|||
PARAMETRIZE { currentHP = 200; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
|
|
@ -305,11 +305,11 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills one opposing mon an
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills one opposing mon and a partner it believes is about to die")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); Moves(MOVE_CELEBRATE, MOVE_SCRATCH); }
|
||||
|
|
@ -324,11 +324,11 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills one opposing mon an
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills both opposing mons")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
|
|
@ -342,7 +342,7 @@ AI_DOUBLE_BATTLE_TEST("AI will choose Earthquake if it kills both opposing mons"
|
|||
AI_DOUBLE_BATTLE_TEST("AI will trigger its ally's Weakness Policy")
|
||||
{
|
||||
ASSUME(gItemsInfo[ITEM_WEAKNESS_POLICY].holdEffect == HOLD_EFFECT_WEAKNESS_POLICY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
|
||||
u32 species;
|
||||
|
|
@ -350,7 +350,7 @@ AI_DOUBLE_BATTLE_TEST("AI will trigger its ally's Weakness Policy")
|
|||
PARAMETRIZE { species = SPECIES_CLEFFA; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
|
@ -366,7 +366,7 @@ AI_DOUBLE_BATTLE_TEST("AI will trigger its ally's Weakness Policy")
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide (doubles)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
|
||||
u32 aiFlags;
|
||||
|
|
@ -391,7 +391,7 @@ AI_DOUBLE_BATTLE_TEST("AI will only explode and kill everything on the field wit
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("Battler 3 has Battler 1 AI flags set correctly (doubles)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
|
||||
u32 aiFlags;
|
||||
|
|
@ -421,13 +421,13 @@ AI_DOUBLE_BATTLE_TEST("Battler 3 has Battler 1 AI flags set correctly (doubles)"
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_LAVA_PLUME) == TYPE_FIRE);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
|
||||
enum Ability ability;
|
||||
|
|
@ -446,7 +446,7 @@ AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners")
|
|||
PARAMETRIZE { species = SPECIES_ORTHWORM; ability = ABILITY_EARTH_EATER; move = MOVE_EARTHQUAKE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
|
|
@ -463,9 +463,9 @@ AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners")
|
|||
AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (gen 4)")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||
|
||||
enum Ability ability;
|
||||
|
|
@ -488,9 +488,9 @@ AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (ge
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (gen 5+)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||
|
||||
enum Ability ability;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
AI_DOUBLE_BATTLE_TEST("AI_FLAG_ATTACKS_PARTNER is willing to kill either the partner or the player")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
|
||||
u32 move, level;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
AI_MULTI_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide (multi)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
|
||||
u32 aiFlags;
|
||||
|
|
@ -34,7 +34,7 @@ AI_MULTI_BATTLE_TEST("AI will only explode and kill everything on the field with
|
|||
|
||||
AI_ONE_VS_TWO_BATTLE_TEST("AI will only explode and kill everything on the field with Risky or Will Suicide (1v2)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
|
||||
u32 aiFlags;
|
||||
|
|
@ -98,7 +98,7 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner makes sensible move selections in battle (
|
|||
|
||||
AI_TWO_VS_ONE_BATTLE_TEST("Battler 3 has Battler 1 AI flags set correctly (2v1)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
|
||||
u32 aiFlags;
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ SINGLE_BATTLE_TEST("Primal reversion happens immediately if it was brought in by
|
|||
DOUBLE_BATTLE_TEST("Primal reversion triggers for multiple battlers if multiple fainted the previous turn")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_CATERPIE) { HP(1); }
|
||||
PLAYER(SPECIES_RESHIRAM);
|
||||
|
|
@ -263,7 +263,7 @@ DOUBLE_BATTLE_TEST("Primal reversion triggers for all battlers if multiple faint
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_CATERPIE) { HP(1); }
|
||||
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
|
||||
|
|
@ -291,7 +291,7 @@ DOUBLE_BATTLE_TEST("Primal reversion and other switch-in effects trigger for all
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB);
|
||||
ASSUME(GetMoveEffect(MOVE_SPIKES) == EFFECT_SPIKES);
|
||||
ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES);
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ DOUBLE_BATTLE_TEST("Shell Bell heals accumulated damage for spread moves")
|
|||
const u16 maxHp = 200;
|
||||
const u16 initHp = 1;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_ARIADOS) { MaxHP(maxHp); HP(initHp); Item(ITEM_SHELL_BELL); }
|
||||
PLAYER(SPECIES_WOBBUFFET) {}
|
||||
OPPONENT(SPECIES_GYARADOS) {}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ DOUBLE_BATTLE_TEST("Throat Spray activates after both hits of a spread move")
|
|||
s16 firstHit, secondHit;
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_THROAT_SPRAY); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ DOUBLE_BATTLE_TEST("Moves do not fail if an alive partner is the target")
|
|||
DOUBLE_BATTLE_TEST("Moves fail if they target into a Pokémon that was fainted by the previous move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
|
|
@ -296,7 +296,7 @@ DOUBLE_BATTLE_TEST("Moves fail if they target into a Pokémon that was fainted b
|
|||
DOUBLE_BATTLE_TEST("Moves that target the field are not going to fail if one mon fainted by the previous move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ DOUBLE_BATTLE_TEST("Ally Switch changes the position of battlers")
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SCREECH) == EFFECT_DEFENSE_DOWN_2);
|
||||
ASSUME(GetMoveTarget(MOVE_SCREECH) == MOVE_TARGET_SELECTED);
|
||||
ASSUME(GetMoveTarget(MOVE_SCREECH) == TARGET_SELECTED);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); } // Wobb is playerLeft, but it'll be Wynaut after Ally Switch
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(4); }
|
||||
OPPONENT(SPECIES_KADABRA) { Speed(3); }
|
||||
|
|
@ -170,7 +170,7 @@ DOUBLE_BATTLE_TEST("Ally Switch - move fails if the target was ally which change
|
|||
DOUBLE_BATTLE_TEST("Ally Switch doesn't make self-targeting status moves fail")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HARDEN) == MOVE_TARGET_USER);
|
||||
ASSUME(GetMoveTarget(MOVE_HARDEN) == TARGET_USER);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -365,9 +365,9 @@ DOUBLE_BATTLE_TEST("Protect: Wide Guard protects self and ally from multi-target
|
|||
PARAMETRIZE { move = MOVE_HYPER_VOICE; } // 2 foes
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SCRATCH) == MOVE_TARGET_SELECTED);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SCRATCH) == TARGET_SELECTED);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
@ -407,7 +407,7 @@ DOUBLE_BATTLE_TEST("Protect: Wide Guard can not fail on consecutive turns (Gen6+
|
|||
PASSES_RANDOMLY(passes, 2);
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_WIDE_GUARD, config);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
@ -503,8 +503,8 @@ DOUBLE_BATTLE_TEST("Protect: Crafty Shield protects self and ally from status mo
|
|||
PARAMETRIZE { move = MOVE_SCRATCH; targetOpponent = opponentRight; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_LEER) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_LEER) == TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
ASSUME(GetMoveCategory(MOVE_HYPER_VOICE) == DAMAGE_CATEGORY_SPECIAL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ SINGLE_BATTLE_TEST("Shell Trap does not activate if battler faints before being
|
|||
DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 1 and attacks both opponents")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(2); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
|
|
@ -122,7 +122,7 @@ DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 1 a
|
|||
DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 2 and attacks both opponents")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(2); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
|
|
@ -146,7 +146,7 @@ DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 2 a
|
|||
DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 3 and attacks both opponents")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(7); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
|
|
@ -170,7 +170,7 @@ DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 3 a
|
|||
DOUBLE_BATTLE_TEST("Shell Trap targets correctly if one of the opponents has fainted")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_SHELL_TRAP) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_GRENINJA) { Speed(60); }
|
||||
PLAYER(SPECIES_TURTONATOR) { Speed(10); }
|
||||
OPPONENT(SPECIES_BLASTOISE) { Speed(120); }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ DOUBLE_BATTLE_TEST("Speed Down: Cotton Spore does not fail if it is blocked by o
|
|||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_COTTON_SPORE) == EFFECT_SPEED_DOWN_2);
|
||||
ASSUME(GetMoveTarget(MOVE_COTTON_SPORE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_COTTON_SPORE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SHELLDER) { Ability(abilityOne); }
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Tera Starstorm changes from Normal-type to Stellar-type if u
|
|||
DOUBLE_BATTLE_TEST("Tera Starstorm targets both opponents in a double battle if used by Terapagos-Stellar")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_TERA_STARSTORM) == MOVE_TARGET_SELECTED);
|
||||
ASSUME(GetMoveTarget(MOVE_TERA_STARSTORM) == TARGET_SELECTED);
|
||||
PLAYER(SPECIES_TERAPAGOS_STELLAR);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ DOUBLE_BATTLE_TEST("Lava Plume inflicts burn to all adjacent battlers")
|
|||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_LAVA_PLUME, MOVE_EFFECT_BURN) == TRUE);
|
||||
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ DOUBLE_BATTLE_TEST("Spread Moves: No damage will be dealt to a mon in an invulne
|
|||
PARAMETRIZE { attackingMove = MOVE_HYPER_VOICE; invulMove = MOVE_DIVE; }
|
||||
PARAMETRIZE { attackingMove = MOVE_LAVA_PLUME; invulMove = MOVE_DIVE; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_ZAPDOS);
|
||||
|
|
@ -172,7 +172,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: A spread move attack will be weakened by stron
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (right) and Lightning Rod (left)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_MIMIKYU);
|
||||
|
|
@ -191,7 +191,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (right) and
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (left) and Lightning Rod (right)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_MIMIKYU);
|
||||
|
|
@ -210,7 +210,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (left) and L
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Eiscue and Mimikyu (Based on vanilla games)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveCategory(MOVE_EARTHQUAKE) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_EISCUE);
|
||||
|
|
@ -229,7 +229,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Eiscue and Mimikyu (Based on vanil
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Spread move, Gem Boosted, vs Resist Berries")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(40); Item(ITEM_NORMAL_GEM); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(30); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_CHILAN_BERRY); }
|
||||
|
|
@ -249,7 +249,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Spread move, Gem Boosted, vs Resist Berries")
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Explosion, Gem Boosted, vs Resist Berries")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveTarget(MOVE_EXPLOSION) == TARGET_FOES_AND_ALLY);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(40); Item(ITEM_NORMAL_GEM); }
|
||||
PLAYER(SPECIES_MISDREAVUS) { Speed(30); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_CHILAN_BERRY); }
|
||||
|
|
@ -270,7 +270,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Explosion, Gem Boosted, vs Resist Berries")
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Spread move vs Eiscue and Mimikyu with 1 Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_RAZOR_LEAF) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_RAZOR_LEAF) == TARGET_BOTH);
|
||||
ASSUME(GetMoveCategory(MOVE_RAZOR_LEAF) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(40); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(30); }
|
||||
|
|
@ -290,7 +290,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Spread move vs Eiscue and Mimikyu with 1 Eject
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Spread move vs Wide Guard")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(40); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(20); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(30); }
|
||||
|
|
@ -310,7 +310,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Spread move vs Wide Guard")
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Spread move vs one protecting mon")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
@ -327,7 +327,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Spread move vs one protecting mon")
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Super Effective Message on both opposing mons")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GOLEM);
|
||||
|
|
@ -345,7 +345,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Super Effective Message on both opposing mons"
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Super Effective Message on both player mons")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_GOLEM);
|
||||
PLAYER(SPECIES_ONIX);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
@ -363,7 +363,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Super Effective Message on both player mons")
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Not very effective Message on both opposing mons")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_CHIKORITA);
|
||||
|
|
@ -381,7 +381,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Not very effective Message on both opposing mo
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Not very effective message on both player mons")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_CHIKORITA);
|
||||
PLAYER(SPECIES_TREECKO);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
|
@ -399,7 +399,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: Not very effective message on both player mons
|
|||
DOUBLE_BATTLE_TEST("Spread Moves: Doesn't affect message on both opposing mons")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == MOVE_TARGET_BOTH);
|
||||
ASSUME(GetMoveTarget(MOVE_PRECIPICE_BLADES) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_PIDGEY);
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ static void BattleTest_Run(void *data)
|
|||
|
||||
if (((DATA.explicitSpeeds[B_POSITION_PLAYER_LEFT] + DATA.explicitSpeeds[B_POSITION_PLAYER_RIGHT]) != (revisedPlayerExplicitSpeeds + revisedPartnerExplicitSpeeds)
|
||||
|| (DATA.explicitSpeeds[B_POSITION_OPPONENT_LEFT] + DATA.explicitSpeeds[B_POSITION_OPPONENT_RIGHT]) != (revisedOpponentAExplicitSpeeds + revisedOpponentBExplicitSpeeds)))
|
||||
|
||||
|
||||
{
|
||||
Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":LSpeed required for all PLAYERs and OPPONENTs");
|
||||
}
|
||||
|
|
@ -1867,19 +1867,19 @@ void OpenPokemonMulti(u32 sourceLine, enum BattlerPosition position, u32 species
|
|||
if ((*partySize == 0) || (*partySize == 1) || (*partySize == 2))
|
||||
*partySize = 3;
|
||||
party = DATA.recordedBattle.playerParty;
|
||||
}
|
||||
}
|
||||
else if (position == B_POSITION_OPPONENT_LEFT) // MULTI_OPPONENT_A
|
||||
{
|
||||
partySize = &DATA.opponentPartySize;
|
||||
party = DATA.recordedBattle.opponentParty;
|
||||
}
|
||||
}
|
||||
else // MULTI_OPPONENT_B
|
||||
{
|
||||
partySize = &DATA.opponentPartySize;
|
||||
if ((*partySize == 0) || (*partySize == 1) || (*partySize == 2))
|
||||
*partySize = 3;
|
||||
party = DATA.recordedBattle.opponentParty;
|
||||
}
|
||||
}
|
||||
INVALID_IF(*partySize >= PARTY_SIZE, "Too many Pokemon in party");
|
||||
DATA.currentPosition = position;
|
||||
DATA.currentPartyIndex = *partySize;
|
||||
|
|
@ -2268,7 +2268,7 @@ static const char *BattlerIdentifier(s32 battlerId)
|
|||
case BATTLE_TEST_AI_TWO_VS_ONE:
|
||||
case BATTLE_TEST_ONE_VS_TWO:
|
||||
case BATTLE_TEST_AI_ONE_VS_TWO:
|
||||
return sBattlerIdentifiersDoubles[battlerId];
|
||||
return sBattlerIdentifiersDoubles[battlerId];
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
|
@ -2438,16 +2438,16 @@ s32 MoveGetTarget(s32 battlerId, u32 moveId, struct MoveContext *ctx, u32 source
|
|||
}
|
||||
else
|
||||
{
|
||||
u32 moveTarget = GetMoveTarget(moveId);
|
||||
if (moveTarget == MOVE_TARGET_RANDOM
|
||||
|| moveTarget == MOVE_TARGET_BOTH
|
||||
|| moveTarget == MOVE_TARGET_DEPENDS
|
||||
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY
|
||||
|| moveTarget == MOVE_TARGET_OPPONENTS_FIELD)
|
||||
enum MoveTarget moveTarget = GetMoveTarget(moveId);
|
||||
if (moveTarget == TARGET_RANDOM
|
||||
|| moveTarget == TARGET_BOTH
|
||||
|| moveTarget == TARGET_DEPENDS
|
||||
|| moveTarget == TARGET_FOES_AND_ALLY
|
||||
|| moveTarget == TARGET_OPPONENTS_FIELD)
|
||||
{
|
||||
target = BATTLE_OPPOSITE(battlerId);
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_SELECTED || moveTarget == MOVE_TARGET_OPPONENT)
|
||||
else if (moveTarget == TARGET_SELECTED || moveTarget == TARGET_OPPONENT)
|
||||
{
|
||||
// In AI Doubles not specified target allows any target for EXPECT_MOVE.
|
||||
if (GetBattleTest()->type != BATTLE_TEST_AI_DOUBLES)
|
||||
|
|
@ -2457,11 +2457,11 @@ s32 MoveGetTarget(s32 battlerId, u32 moveId, struct MoveContext *ctx, u32 source
|
|||
|
||||
target = BATTLE_OPPOSITE(battlerId);
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_USER || moveTarget == MOVE_TARGET_ALL_BATTLERS)
|
||||
else if (moveTarget == TARGET_USER || moveTarget == TARGET_ALL_BATTLERS || moveTarget == TARGET_FIELD)
|
||||
{
|
||||
target = battlerId;
|
||||
}
|
||||
else if (moveTarget == MOVE_TARGET_ALLY)
|
||||
else if (moveTarget == TARGET_ALLY)
|
||||
{
|
||||
target = BATTLE_PARTNER(battlerId);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user