mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-02-21 11:43:37 +01:00
Dynamic move targeting
Properly implement Expanding Force by replacing all instances that read move target from gBattleMoves with a function.
This commit is contained in:
parent
6b8f86c276
commit
fa0b5188bb
@ -163,7 +163,7 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags);
|
||||
void TryToApplyMimicry(u8 battlerId, bool8 various);
|
||||
void TryToRevertMimicry(void);
|
||||
void RestoreBattlerOriginalTypes(u8 battlerId);
|
||||
|
||||
u32 GetMoveTargetType(u8 battlerId, u16 move);
|
||||
// Ability checks
|
||||
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
|
||||
bool32 IsRolePlayBannedAbility(u16 ability);
|
||||
|
@ -521,7 +521,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
u8 atkPriority = GetMovePriority(battlerAtk, move);
|
||||
u16 moveEffect = gBattleMoves[move].effect;
|
||||
s32 moveType;
|
||||
u16 moveTarget = gBattleMoves[move].target;
|
||||
u16 moveTarget = GetMoveTargetType(battlerAtk, move);
|
||||
u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move);
|
||||
u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef);
|
||||
bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk);
|
||||
@ -537,7 +537,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
GET_MOVE_TYPE(move, moveType);
|
||||
|
||||
// check non-user target
|
||||
if (!(gBattleMoves[move].target & MOVE_TARGET_USER))
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
{
|
||||
// handle negative checks on non-user target
|
||||
// check powder moves
|
||||
@ -2336,7 +2336,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gBattleMoves[instructedMove].target & (MOVE_TARGET_SELECTED
|
||||
if (GetMoveTargetType(battlerDef, instructedMove) & (MOVE_TARGET_SELECTED
|
||||
| MOVE_TARGET_DEPENDS
|
||||
| MOVE_TARGET_RANDOM
|
||||
| MOVE_TARGET_BOTH
|
||||
@ -2533,7 +2533,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
// move data
|
||||
u8 moveType = gBattleMoves[move].type;
|
||||
u16 effect = gBattleMoves[move].effect;
|
||||
u16 target = gBattleMoves[move].target;
|
||||
u16 moveTarget = GetMoveTargetType(battlerAtk, move);
|
||||
// ally data
|
||||
u8 battlerAtkPartner = AI_DATA->battlerAtkPartner;
|
||||
u16 atkPartnerAbility = AI_DATA->atkPartnerAbility;
|
||||
@ -2572,7 +2572,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
if (IsAttackBoostMoveEffect(effect))
|
||||
score -= 3;
|
||||
// encourage moves hitting multiple opponents
|
||||
if (!IS_MOVE_STATUS(move) && (gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
if (!IS_MOVE_STATUS(move) && (moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
score += 3;
|
||||
}
|
||||
}
|
||||
@ -2640,7 +2640,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
if (GetMoveDamageResult(move) == MOVE_POWER_OTHER)
|
||||
{
|
||||
// partner ability checks
|
||||
if (!partnerProtecting && gBattleMoves[move].target != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move))
|
||||
if (!partnerProtecting && moveTarget != MOVE_TARGET_BOTH && !DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move))
|
||||
{
|
||||
switch (atkPartnerAbility)
|
||||
{
|
||||
@ -2840,7 +2840,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
|
||||
if (instructedMove != MOVE_NONE
|
||||
&& !IS_MOVE_STATUS(instructedMove)
|
||||
&& gBattleMoves[instructedMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) //Use instruct on multi-target moves
|
||||
&& (GetMoveTargetType(battlerAtkPartner, instructedMove) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) // Use instruct on multi-target moves
|
||||
{
|
||||
RETURN_SCORE_PLUS(1);
|
||||
}
|
||||
@ -3631,24 +3631,24 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
case MOVE_WIDE_GUARD:
|
||||
if (predictedMove != MOVE_NONE && gBattleMoves[predictedMove].target & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
if (predictedMove != MOVE_NONE && GetMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))
|
||||
{
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
}
|
||||
else if (isDoubleBattle && gBattleMoves[AI_DATA->partnerMove].target & MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (isDoubleBattle && GetMoveTargetType(AI_DATA->battlerAtkPartner, AI_DATA->partnerMove) & MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
if (AI_DATA->atkAbility != ABILITY_TELEPATHY)
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
}
|
||||
break;
|
||||
case MOVE_CRAFTY_SHIELD:
|
||||
if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(gBattleMoves[predictedMove].target & MOVE_TARGET_USER))
|
||||
if (predictedMove != MOVE_NONE && IS_MOVE_STATUS(predictedMove) && !(GetMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
|
||||
case MOVE_MAT_BLOCK:
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn && predictedMove != MOVE_NONE
|
||||
&& !IS_MOVE_STATUS(predictedMove) && !(gBattleMoves[predictedMove].target & MOVE_TARGET_USER))
|
||||
&& !IS_MOVE_STATUS(predictedMove) && !(GetMoveTargetType(battlerDef, predictedMove) & MOVE_TARGET_USER))
|
||||
ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score);
|
||||
break;
|
||||
case MOVE_KINGS_SHIELD:
|
||||
@ -4093,7 +4093,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
score += 10;
|
||||
break;
|
||||
case EFFECT_MAGIC_COAT:
|
||||
if (IS_MOVE_STATUS(predictedMove) && gBattleMoves[predictedMove].target & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
if (IS_MOVE_STATUS(predictedMove) && GetMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
|
||||
score += 3;
|
||||
break;
|
||||
case EFFECT_RECYCLE:
|
||||
|
@ -1919,9 +1919,8 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
|
||||
if (ignoreStatus && IS_MOVE_STATUS(moves[i]))
|
||||
continue;
|
||||
else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0)
|
||||
|| gBattleMoves[moves[i]].target & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
|| GetMoveTargetType(battlerAtk, moves[i]) & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
continue;
|
||||
|
||||
if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck)
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2195,7 +2195,7 @@ void DoMoveAnim(u16 move)
|
||||
gBattleAnimAttacker = gBattlerAttacker;
|
||||
gBattleAnimTarget = gBattlerTarget;
|
||||
// Make sure the anim target of moves hitting everyone is at the opposite side.
|
||||
if (gBattleMoves[move].target & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle())
|
||||
if (GetMoveTargetType(gBattlerAttacker, move) & MOVE_TARGET_FOES_AND_ALLY && IsDoubleBattle())
|
||||
{
|
||||
while (GET_BATTLER_SIDE(gBattleAnimAttacker) == GET_BATTLER_SIDE(gBattleAnimTarget))
|
||||
{
|
||||
|
@ -1586,9 +1586,9 @@ static void OpponentHandleChooseMove(void)
|
||||
BtlController_EmitTwoReturnValues(1, 15, gBattlerTarget);
|
||||
break;
|
||||
default:
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
@ -1611,7 +1611,7 @@ static void OpponentHandleChooseMove(void)
|
||||
move = moveInfo->moves[chosenMoveId];
|
||||
} while (move == MOVE_NONE);
|
||||
|
||||
if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
if (GetMoveTargetType(gActiveBattler, move) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gActiveBattler << 8));
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8));
|
||||
|
@ -360,6 +360,7 @@ static void HandleInputChooseTarget(void)
|
||||
s32 i;
|
||||
static const u8 identities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT};
|
||||
u16 move = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler]);
|
||||
u16 moveTarget = GetMoveTargetType(gActiveBattler, move);
|
||||
|
||||
DoBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX, 15, 1);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
@ -400,7 +401,7 @@ static void HandleInputChooseTarget(void)
|
||||
PlaySE(SE_SELECT);
|
||||
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_HideAsMoveTarget;
|
||||
|
||||
if (gBattleMoves[move].target == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
{
|
||||
gMultiUsePlayerCursor ^= BIT_FLANK;
|
||||
}
|
||||
@ -429,7 +430,7 @@ static void HandleInputChooseTarget(void)
|
||||
case B_POSITION_PLAYER_RIGHT:
|
||||
if (gActiveBattler != gMultiUsePlayerCursor)
|
||||
i++;
|
||||
else if (gBattleMoves[move].target & MOVE_TARGET_USER_OR_SELECTED)
|
||||
else if (moveTarget & MOVE_TARGET_USER_OR_SELECTED)
|
||||
i++;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
@ -449,7 +450,7 @@ static void HandleInputChooseTarget(void)
|
||||
PlaySE(SE_SELECT);
|
||||
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_HideAsMoveTarget;
|
||||
|
||||
if (gBattleMoves[move].target == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
if (moveTarget == (MOVE_TARGET_USER | MOVE_TARGET_ALLY))
|
||||
{
|
||||
gMultiUsePlayerCursor ^= BIT_FLANK;
|
||||
}
|
||||
@ -478,7 +479,7 @@ static void HandleInputChooseTarget(void)
|
||||
case B_POSITION_PLAYER_RIGHT:
|
||||
if (gActiveBattler != gMultiUsePlayerCursor)
|
||||
i++;
|
||||
else if (gBattleMoves[move].target & MOVE_TARGET_USER_OR_SELECTED)
|
||||
else if (moveTarget & MOVE_TARGET_USER_OR_SELECTED)
|
||||
i++;
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
@ -609,16 +610,9 @@ static void HandleInputChooseMove(void)
|
||||
else
|
||||
moveTarget = MOVE_TARGET_SELECTED;
|
||||
}
|
||||
else if (moveInfo->moves[gMoveSelectionCursor[gActiveBattler]] == MOVE_EXPANDING_FORCE)
|
||||
{
|
||||
if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
moveTarget = MOVE_TARGET_BOTH;
|
||||
else
|
||||
moveTarget = MOVE_TARGET_SELECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
moveTarget = gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].target;
|
||||
moveTarget = GetMoveTargetType(gActiveBattler, moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]);
|
||||
}
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
|
@ -1526,9 +1526,9 @@ static void PlayerPartnerHandleChooseMove(void)
|
||||
BattleAI_SetupAIData(0xF);
|
||||
chosenMoveId = BattleAI_ChooseMoveOrAction();
|
||||
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED))
|
||||
if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
if (GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]) & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
|
@ -38,7 +38,7 @@ extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow;
|
||||
extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow;
|
||||
|
||||
// this file's functions
|
||||
static u8 GetBattlePalaceMoveGroup(u16 move);
|
||||
static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move);
|
||||
static u16 GetBattlePalaceTarget(void);
|
||||
static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite);
|
||||
static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId);
|
||||
@ -155,7 +155,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
{
|
||||
if (moveInfo->moves[i] == MOVE_NONE)
|
||||
break;
|
||||
if (selectedGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]) && moveInfo->currentPp[i] != 0)
|
||||
if (selectedGroup == GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) && moveInfo->currentPp[i] != 0)
|
||||
selectedMoves |= gBitTable[i];
|
||||
}
|
||||
|
||||
@ -181,11 +181,11 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
{
|
||||
// validMoveFlags is used here as a bitfield for which moves can be used for each move group type
|
||||
// first 4 bits are for attack (1 for each move), then 4 bits for defense, and 4 for support
|
||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
|
||||
if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
|
||||
validMoveFlags += (1 << 0);
|
||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
|
||||
if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
|
||||
validMoveFlags += (1 << 4);
|
||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
|
||||
if (GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
|
||||
validMoveFlags += (1 << 8);
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
do
|
||||
{
|
||||
i = Random() % MAX_MON_MOVES;
|
||||
if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]))
|
||||
if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(gActiveBattler, moveInfo->moves[i]))
|
||||
chosenMoveId = i;
|
||||
} while (chosenMoveId == -1);
|
||||
}
|
||||
@ -251,7 +251,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
moveTarget = gBattleMoves[moveInfo->moves[chosenMoveId]].target;
|
||||
moveTarget = GetMoveTargetType(gActiveBattler, moveInfo->moves[chosenMoveId]);
|
||||
}
|
||||
|
||||
if (moveTarget & MOVE_TARGET_USER)
|
||||
@ -273,9 +273,9 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
||||
#undef numValidMoveGroups
|
||||
#undef validMoveGroup
|
||||
|
||||
static u8 GetBattlePalaceMoveGroup(u16 move)
|
||||
static u8 GetBattlePalaceMoveGroup(u8 battlerId, u16 move)
|
||||
{
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetMoveTargetType(battlerId, move))
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_USER_OR_SELECTED:
|
||||
|
@ -1313,12 +1313,12 @@ static const u8 sBattlePalaceNatureToFlavorTextId[NUM_NATURES] =
|
||||
[NATURE_QUIRKY] = B_MSG_EAGER_FOR_MORE,
|
||||
};
|
||||
|
||||
static bool32 NoTargetPresent(u32 move)
|
||||
static bool32 NoTargetPresent(u8 battlerId, u32 move)
|
||||
{
|
||||
if (!IsBattlerAlive(gBattlerTarget))
|
||||
gBattlerTarget = GetMoveTarget(move, 0);
|
||||
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetMoveTargetType(battlerId, move))
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
case MOVE_TARGET_DEPENDS:
|
||||
@ -1459,7 +1459,7 @@ static void Cmd_attackcanceler(void)
|
||||
}
|
||||
|
||||
gHitMarker |= HITMARKER_OBEYS;
|
||||
if (NoTargetPresent(gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
|
||||
if (NoTargetPresent(gBattlerAttacker, gCurrentMove) && (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce;
|
||||
if (!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
|
||||
@ -1741,6 +1741,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
static void Cmd_accuracycheck(void)
|
||||
{
|
||||
u16 type, move = T2_READ_16(gBattlescriptCurrInstr + 5);
|
||||
u16 moveTarget = GetMoveTargetType(gBattlerAttacker, move);
|
||||
|
||||
if (move == ACC_CURR_MOVE)
|
||||
move = gCurrentMove;
|
||||
@ -1770,7 +1771,7 @@ static void Cmd_accuracycheck(void)
|
||||
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
|
||||
(gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY))
|
||||
(moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK;
|
||||
else
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_MISSED;
|
||||
@ -1804,7 +1805,7 @@ static void Cmd_ppreduce(void)
|
||||
|
||||
if (!gSpecialStatuses[gBattlerAttacker].ppNotAffectedByPressure)
|
||||
{
|
||||
switch (gBattleMoves[gCurrentMove].target)
|
||||
switch (GetMoveTargetType(gBattlerAttacker, gCurrentMove))
|
||||
{
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
@ -2103,6 +2104,8 @@ static void Cmd_multihitresultmessage(void)
|
||||
|
||||
static void Cmd_attackanimation(void)
|
||||
{
|
||||
u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
@ -2119,9 +2122,9 @@ static void Cmd_attackanimation(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH
|
||||
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY
|
||||
|| gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS)
|
||||
if ((moveTarget & MOVE_TARGET_BOTH
|
||||
|| moveTarget & MOVE_TARGET_FOES_AND_ALLY
|
||||
|| moveTarget & MOVE_TARGET_DEPENDS)
|
||||
&& gBattleScripting.animTargetsHit)
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
@ -5237,6 +5240,8 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon.
|
||||
{
|
||||
u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
// Set a flag if move hits either target (for throat spray that can't check damage)
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
@ -5245,14 +5250,13 @@ static void Cmd_moveend(void)
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& !gProtectStructs[gBattlerAttacker].chargingTurn
|
||||
&& (gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH
|
||||
|| gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY
|
||||
|| (gBattleMoves[gCurrentMove].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN)))
|
||||
&& (moveTarget == MOVE_TARGET_BOTH
|
||||
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
&& !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
|
||||
{
|
||||
u8 battlerId;
|
||||
|
||||
if (gBattleMoves[gCurrentMove].target == MOVE_TARGET_FOES_AND_ALLY)
|
||||
if (moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
for (battlerId = gBattlerTarget + 1; battlerId < gBattlersCount; battlerId++)
|
||||
@ -5288,6 +5292,7 @@ static void Cmd_moveend(void)
|
||||
RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove);
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
case MOVEEND_EJECT_BUTTON:
|
||||
if (gCurrentMove != MOVE_DRAGON_TAIL
|
||||
&& gCurrentMove != MOVE_CIRCLE_THROW
|
||||
@ -9506,7 +9511,7 @@ static void Cmd_jumpifnexttargetvalid(void)
|
||||
|
||||
for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER))
|
||||
if (gBattlerTarget == gBattlerAttacker && !(GetMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER))
|
||||
continue;
|
||||
if (IsBattlerAlive(gBattlerTarget))
|
||||
break;
|
||||
@ -12000,7 +12005,7 @@ static void Cmd_selectfirstvalidtarget(void)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER))
|
||||
if (gBattlerTarget == gBattlerAttacker && !(GetMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER))
|
||||
continue;
|
||||
if (IsBattlerAlive(gBattlerTarget))
|
||||
break;
|
||||
|
@ -237,6 +237,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|
||||
void HandleAction_UseMove(void)
|
||||
{
|
||||
u32 i, side, moveType, var = 4;
|
||||
u16 moveTarget = GetMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
|
||||
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
|
||||
if (gBattleStruct->field_91 & gBitTable[gBattlerAttacker] || !IsBattlerAlive(gBattlerAttacker))
|
||||
@ -309,14 +310,14 @@ void HandleAction_UseMove(void)
|
||||
// choose target
|
||||
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove)
|
||||
&& gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED
|
||||
&& moveTarget == MOVE_TARGET_SELECTED
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget))
|
||||
{
|
||||
gBattlerTarget = gSideTimers[side].followmeTarget;
|
||||
}
|
||||
else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
&& gSideTimers[side].followmeTimer == 0
|
||||
&& (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER)
|
||||
&& (gBattleMoves[gCurrentMove].power != 0 || moveTarget != MOVE_TARGET_USER)
|
||||
&& ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|
||||
|| (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER)))
|
||||
{
|
||||
@ -337,7 +338,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
if (var == 4)
|
||||
{
|
||||
if (gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM)
|
||||
if (moveTarget & MOVE_TARGET_RANDOM)
|
||||
{
|
||||
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
|
||||
{
|
||||
@ -354,7 +355,7 @@ void HandleAction_UseMove(void)
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
}
|
||||
}
|
||||
else if (gBattleMoves[gChosenMove].target & MOVE_TARGET_FOES_AND_ALLY)
|
||||
else if (moveTarget & MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
@ -395,7 +396,7 @@ void HandleAction_UseMove(void)
|
||||
}
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM)
|
||||
&& moveTarget & MOVE_TARGET_RANDOM)
|
||||
{
|
||||
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
|
||||
{
|
||||
@ -418,7 +419,7 @@ void HandleAction_UseMove(void)
|
||||
gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
|
||||
}
|
||||
}
|
||||
else if (gBattleMoves[gChosenMove].target == MOVE_TARGET_ALLY)
|
||||
else if (moveTarget == MOVE_TARGET_ALLY)
|
||||
{
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))
|
||||
gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker);
|
||||
@ -426,7 +427,7 @@ void HandleAction_UseMove(void)
|
||||
gBattlerTarget = gBattlerAttacker;
|
||||
}
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& gBattleMoves[gChosenMove].target == MOVE_TARGET_FOES_AND_ALLY)
|
||||
&& moveTarget == MOVE_TARGET_FOES_AND_ALLY)
|
||||
{
|
||||
for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++)
|
||||
{
|
||||
@ -4668,7 +4669,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_MOVES_BLOCK: // 2
|
||||
if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(gBattleMoves[move].target & MOVE_TARGET_USER))
|
||||
{
|
||||
u16 moveTarget = GetMoveTargetType(battler, move);
|
||||
|
||||
if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(moveTarget & MOVE_TARGET_USER))
|
||||
|| (gLastUsedAbility == ABILITY_BULLETPROOF && gBattleMoves[move].flags & FLAG_BALLISTIC))
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
@ -4691,14 +4695,14 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
else if (BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE)
|
||||
&& !(IS_MOVE_STATUS(move) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE))
|
||||
{
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster;
|
||||
effect = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ABILITYEFFECT_ABSORBING: // 3
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
@ -7257,15 +7261,12 @@ u32 GetMoveTarget(u16 move, u8 setTarget)
|
||||
if (setTarget)
|
||||
moveTarget = setTarget - 1;
|
||||
else
|
||||
moveTarget = gBattleMoves[move].target;
|
||||
|
||||
moveTarget = GetMoveTargetType(gBattlerAttacker, move);
|
||||
|
||||
// Special cases
|
||||
if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
|
||||
moveTarget = MOVE_TARGET_USER;
|
||||
|
||||
if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
moveTarget = MOVE_TARGET_BOTH;
|
||||
|
||||
switch (moveTarget)
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
@ -7528,7 +7529,7 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move)
|
||||
else if (gProtectStructs[battlerId].protected)
|
||||
return TRUE;
|
||||
else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD
|
||||
&& gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
|
||||
&& GetMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
|
||||
return TRUE;
|
||||
else if (gProtectStructs[battlerId].banefulBunkered)
|
||||
return TRUE;
|
||||
@ -7654,7 +7655,7 @@ u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc)
|
||||
|
||||
u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||
{
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetMoveTargetType(gBattlerAttacker, move))
|
||||
{
|
||||
case MOVE_TARGET_BOTH:
|
||||
return IsBattlerAlive(battlerDef)
|
||||
@ -9818,7 +9819,7 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 chec
|
||||
return FALSE;
|
||||
if (GetBattlerSide(battlerPrankster) == GetBattlerSide(battlerDef))
|
||||
return FALSE;
|
||||
if (checkTarget && (gBattleMoves[move].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)))
|
||||
if (checkTarget && (GetMoveTargetType(battlerPrankster, move) & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)))
|
||||
return FALSE;
|
||||
if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK))
|
||||
return FALSE;
|
||||
@ -9850,3 +9851,16 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Gets move target before redirection effects etc. are applied
|
||||
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
|
||||
u32 GetMoveTargetType(u8 battlerId, u16 move)
|
||||
{
|
||||
u32 target;
|
||||
|
||||
if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE
|
||||
&& IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN))
|
||||
return MOVE_TARGET_BOTH;
|
||||
else
|
||||
return gBattleMoves[move].target;
|
||||
}
|
||||
|
@ -5388,7 +5388,7 @@ static void SetBattleTargetSpritePosition(void)
|
||||
|
||||
static void SetMoveTargetPosition(u16 move)
|
||||
{
|
||||
switch (gBattleMoves[move].target)
|
||||
switch (GetMoveTargetType(gBattlerAttacker, move))
|
||||
{
|
||||
case MOVE_TARGET_USER_OR_SELECTED:
|
||||
case MOVE_TARGET_USER:
|
||||
|
Loading…
x
Reference in New Issue
Block a user