Document ChooseMoveAndTargetInBattlePalace
This commit is contained in:
+6
-1
@@ -392,7 +392,7 @@ struct BattleStruct
|
|||||||
u8 expGetterBattlerId;
|
u8 expGetterBattlerId;
|
||||||
u8 unused_5;
|
u8 unused_5;
|
||||||
u8 absentBattlerFlags;
|
u8 absentBattlerFlags;
|
||||||
u8 palaceFlags; // First 4 bits are "is < 50% HP and not asleep" for each battler, last 4 bits are selected moves to pass to AI
|
u8 palaceFlags; // First 4 bits are "is <= 50% HP and not asleep" for each battler, last 4 bits are selected moves to pass to AI
|
||||||
u8 field_93; // related to choosing pokemon?
|
u8 field_93; // related to choosing pokemon?
|
||||||
u8 wallyBattleState;
|
u8 wallyBattleState;
|
||||||
u8 wallyMovesState;
|
u8 wallyMovesState;
|
||||||
@@ -440,6 +440,11 @@ struct BattleStruct
|
|||||||
u8 alreadyStatusedMoveAttempt; // As bits for battlers; For example when using Thunder Wave on an already paralyzed pokemon.
|
u8 alreadyStatusedMoveAttempt; // As bits for battlers; For example when using Thunder Wave on an already paralyzed pokemon.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
|
||||||
|
// and 1 flag per battler to indicate whether the battler is awake and at <= 50% HP (which affects move choice).
|
||||||
|
// The assert below is to ensure palaceFlags is large enough to store these flags without overlap.
|
||||||
|
STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLERS_COUNT + MAX_MON_MOVES, PalaceFlagsTooSmall)
|
||||||
|
|
||||||
#define F_DYNAMIC_TYPE_1 (1 << 6)
|
#define F_DYNAMIC_TYPE_1 (1 << 6)
|
||||||
#define F_DYNAMIC_TYPE_2 (1 << 7)
|
#define F_DYNAMIC_TYPE_2 (1 << 7)
|
||||||
#define DYNAMIC_TYPE_MASK (F_DYNAMIC_TYPE_1 - 1)
|
#define DYNAMIC_TYPE_MASK (F_DYNAMIC_TYPE_1 - 1)
|
||||||
|
|||||||
+56
-33
@@ -121,9 +121,9 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
|||||||
#define selectedGroup percent
|
#define selectedGroup percent
|
||||||
#define selectedMoves var2
|
#define selectedMoves var2
|
||||||
#define moveTarget var1
|
#define moveTarget var1
|
||||||
#define validMoveFlags var1
|
#define numMovesPerGroup var1
|
||||||
#define numValidMoveGroups var2
|
#define numMultipleMoveGroups var2
|
||||||
#define validMoveGroup var2
|
#define randSelectGroup var2
|
||||||
|
|
||||||
// If battler is < 50% HP and not asleep, use second set of move group likelihoods
|
// If battler is < 50% HP and not asleep, use second set of move group likelihoods
|
||||||
// otherwise use first set
|
// otherwise use first set
|
||||||
@@ -172,32 +172,45 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
|||||||
{
|
{
|
||||||
if (unusableMovesBits != ALL_MOVES_MASK)
|
if (unusableMovesBits != ALL_MOVES_MASK)
|
||||||
{
|
{
|
||||||
validMoveFlags = 0, numValidMoveGroups = 0;
|
numMovesPerGroup = 0, numMultipleMoveGroups = 0;
|
||||||
|
|
||||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||||
{
|
{
|
||||||
// validMoveFlags is used here as a bitfield for which moves can be used for each move group type
|
// Count the number of usable moves the battler has in each move group.
|
||||||
// first 4 bits are for attack (1 for each move), then 4 bits for defense, and 4 for support
|
// The totals will be stored separately in 3 groups of 4 bits each in numMovesPerGroup.
|
||||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
|
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_ATTACK && !(gBitTable[i] & unusableMovesBits))
|
||||||
validMoveFlags += (1 << 0);
|
numMovesPerGroup += (1 << 0);
|
||||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
|
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_DEFENSE && !(gBitTable[i] & unusableMovesBits))
|
||||||
validMoveFlags += (1 << 4);
|
numMovesPerGroup += (1 << 4);
|
||||||
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
|
if (GetBattlePalaceMoveGroup(moveInfo->moves[i]) == PALACE_MOVE_GROUP_SUPPORT && !(gBitTable[i] & unusableMovesBits))
|
||||||
validMoveFlags += (1 << 8);
|
numMovesPerGroup += (1 << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the move groups the pokemon has
|
// Count the number of move groups for which the battler has at least 2 usable moves.
|
||||||
if ((validMoveFlags & 0xF) > 1)
|
// This is a roundabout way to determine if there is a move group that should be
|
||||||
numValidMoveGroups++;
|
// preferred, because it has multiple move options and the others do not.
|
||||||
if ((validMoveFlags & 0xF0) > 0x1F)
|
// The condition intended to check the total for the Support group is accidentally
|
||||||
numValidMoveGroups++;
|
// checking the Defense total, and is never true. As a result the preferences for
|
||||||
if ((validMoveFlags & 0xF0) > 0x1FF)
|
// random move selection here will skew away from the Support move group.
|
||||||
numValidMoveGroups++;
|
if ((numMovesPerGroup & 0xF) >= 2)
|
||||||
|
numMultipleMoveGroups++;
|
||||||
|
if ((numMovesPerGroup & (0xF << 4)) >= (2 << 4))
|
||||||
|
numMultipleMoveGroups++;
|
||||||
|
#ifdef BUGFIX
|
||||||
|
if ((numMovesPerGroup & (0xF << 8)) >= (2 << 8))
|
||||||
|
#else
|
||||||
|
if ((numMovesPerGroup & (0xF << 4)) >= (2 << 8))
|
||||||
|
#endif
|
||||||
|
numMultipleMoveGroups++;
|
||||||
|
|
||||||
|
|
||||||
// If more than 1 possible move group, or no possible move groups
|
// By this point we already know the battler only has usable moves from at most 2 of the 3 move groups,
|
||||||
// then choose move randomly
|
// because they had no usable moves from the move group that was selected based on Nature.
|
||||||
if (numValidMoveGroups > 1 || numValidMoveGroups == 0)
|
//
|
||||||
|
// The below condition is effectively 'numMultipleMoveGroups != 1'.
|
||||||
|
// There is no stand-out group with multiple moves to choose from, so we pick randomly.
|
||||||
|
// Note that because of the bug above the battler may actually have any number of Support moves.
|
||||||
|
if (numMultipleMoveGroups > 1 || numMultipleMoveGroups == 0)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -206,27 +219,36 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
|||||||
chosenMoveId = i;
|
chosenMoveId = i;
|
||||||
} while (chosenMoveId == -1);
|
} while (chosenMoveId == -1);
|
||||||
}
|
}
|
||||||
// Otherwise randomly choose move of only available move group
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((validMoveFlags & 0xF) > 1)
|
// The battler has just 1 move group with multiple move options to choose from.
|
||||||
validMoveGroup = PALACE_MOVE_GROUP_ATTACK;
|
// Choose a move randomly from this group.
|
||||||
if ((validMoveFlags & 0xF0) > 0x1F)
|
|
||||||
validMoveGroup = PALACE_MOVE_GROUP_DEFENSE;
|
// Same bug as the previous set of conditions (the condition for Support is never true).
|
||||||
if ((validMoveFlags & 0xF0) > 0x1FF)
|
// This bug won't cause a softlock below, because if Support is the only group with multiple
|
||||||
validMoveGroup = PALACE_MOVE_GROUP_SUPPORT;
|
// moves then it won't have been counted, and the 'numMultipleMoveGroups == 0' above will be true.
|
||||||
|
if ((numMovesPerGroup & 0xF) >= 2)
|
||||||
|
randSelectGroup = PALACE_MOVE_GROUP_ATTACK;
|
||||||
|
if ((numMovesPerGroup & (0xF << 4)) >= (2 << 4))
|
||||||
|
randSelectGroup = PALACE_MOVE_GROUP_DEFENSE;
|
||||||
|
#ifdef BUGFIX
|
||||||
|
if ((numMovesPerGroup & (0xF << 8)) >= (2 << 8))
|
||||||
|
#else
|
||||||
|
if ((numMovesPerGroup & (0xF << 4)) >= (2 << 8))
|
||||||
|
#endif
|
||||||
|
randSelectGroup = PALACE_MOVE_GROUP_SUPPORT;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
i = Random() % MAX_MON_MOVES;
|
i = Random() % MAX_MON_MOVES;
|
||||||
if (!(gBitTable[i] & unusableMovesBits) && validMoveGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]))
|
if (!(gBitTable[i] & unusableMovesBits) && randSelectGroup == GetBattlePalaceMoveGroup(moveInfo->moves[i]))
|
||||||
chosenMoveId = i;
|
chosenMoveId = i;
|
||||||
} while (chosenMoveId == -1);
|
} while (chosenMoveId == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a move was selected (and in this case was not from the Nature-chosen group)
|
// Because the selected move was not from the Nature-chosen move group there's a 50% chance
|
||||||
// then there's a 50% chance it won't be used anyway
|
// that it will be unable to use it. This could have been checked earlier to avoid the above work.
|
||||||
if (Random() % 100 > 49)
|
if (Random() % 100 >= 50)
|
||||||
{
|
{
|
||||||
gProtectStructs[gActiveBattler].palaceUnableToUseMove = TRUE;
|
gProtectStructs[gActiveBattler].palaceUnableToUseMove = TRUE;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -234,6 +256,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// All the battler's moves were flagged as unusable.
|
||||||
gProtectStructs[gActiveBattler].palaceUnableToUseMove = TRUE;
|
gProtectStructs[gActiveBattler].palaceUnableToUseMove = TRUE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -266,9 +289,9 @@ u16 ChooseMoveAndTargetInBattlePalace(void)
|
|||||||
#undef selectedGroup
|
#undef selectedGroup
|
||||||
#undef selectedMoves
|
#undef selectedMoves
|
||||||
#undef moveTarget
|
#undef moveTarget
|
||||||
#undef validMoveFlags
|
#undef numMovesPerGroup
|
||||||
#undef numValidMoveGroups
|
#undef numMultipleMoveGroups
|
||||||
#undef validMoveGroup
|
#undef randSelectGroup
|
||||||
|
|
||||||
static u8 GetBattlePalaceMoveGroup(u16 move)
|
static u8 GetBattlePalaceMoveGroup(u16 move)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -849,7 +849,7 @@ static const u8 sBallCatchBonuses[] =
|
|||||||
// In Battle Palace, moves are chosen based on the pokemons nature rather than by the player
|
// In Battle Palace, moves are chosen based on the pokemons nature rather than by the player
|
||||||
// Moves are grouped into "Attack", "Defense", or "Support" (see PALACE_MOVE_GROUP_*)
|
// Moves are grouped into "Attack", "Defense", or "Support" (see PALACE_MOVE_GROUP_*)
|
||||||
// Each nature has a certain percent chance of selecting a move from a particular group
|
// Each nature has a certain percent chance of selecting a move from a particular group
|
||||||
// and a separate percent chance for each group when below 50% HP
|
// and a separate percent chance for each group when at or below 50% HP
|
||||||
// The table below doesn't list percentages for Support because you can subtract the other two
|
// The table below doesn't list percentages for Support because you can subtract the other two
|
||||||
// Support percentages are listed in comments off to the side instead
|
// Support percentages are listed in comments off to the side instead
|
||||||
#define PALACE_STYLE(atk, def, atkLow, defLow) {atk, atk + def, atkLow, atkLow + defLow}
|
#define PALACE_STYLE(atk, def, atkLow, defLow) {atk, atk + def, atkLow, atkLow + defLow}
|
||||||
|
|||||||
Reference in New Issue
Block a user