Decomped CanUseStatusMove()

This commit is contained in:
AnonymousRandomPerson
2022-02-24 23:38:21 -05:00
parent 40a34fafd6
commit 6e56b9f034
10 changed files with 1395 additions and 1543 deletions

View File

@@ -5,198 +5,6 @@
.text
thumb_func_start CanUseStatusMove
CanUseStatusMove:
push {r4-r7,lr}
mov r7, r9
mov r6, r8
push {r6,r7}
adds r5, r1, 0
adds r4, r2, 0
mov r8, r3
ldr r1, [sp, 0x1C]
lsls r0, 16
asrs r6, r0, 16
lsls r1, 24
lsrs r1, 24
mov r9, r1
movs r7, 0
movs r0, 0xF
ands r0, r6
adds r1, r0, 0
cmp r1, 0
bne _0807C686
adds r0, r5, 0
adds r1, r4, 0
movs r2, 0
movs r3, 0x1
bl CanTarget
lsls r0, 24
lsrs r0, 24
cmp r0, 0x1
bne _0807C6E0
movs r7, 0x1
b _0807C6E4
_0807C686:
cmp r1, 0x1
beq _0807C6BE
cmp r1, 0x2
bne _0807C692
ldr r1, [r4, 0x70]
b _0807C69C
_0807C692:
cmp r1, 0x5
bne _0807C6B6
ldr r1, [r4, 0x70]
cmp r5, r4
beq _0807C6B2
_0807C69C:
movs r7, 0x1
ldrb r0, [r1, 0x8]
cmp r0, 0x1
beq _0807C6B2
adds r0, r1, 0
adds r0, 0xA4
ldrb r0, [r0]
cmp r0, 0x4
beq _0807C6B2
cmp r0, 0x1
bne _0807C6E0
_0807C6B2:
movs r0, 0
b _0807C7A0
_0807C6B6:
cmp r1, 0x6
bne _0807C6D4
cmp r5, r4
beq _0807C6B2
_0807C6BE:
adds r0, r5, 0
adds r1, r4, 0
movs r2, 0
movs r3, 0x1
bl CanTarget
lsls r0, 24
cmp r0, 0
bne _0807C6E0
movs r7, 0x1
b _0807C6E4
_0807C6D4:
subs r0, 0x3
lsls r0, 16
lsrs r0, 16
cmp r0, 0x1
bhi _0807C6E0
movs r7, 0x1
_0807C6E0:
cmp r7, 0
beq _0807C79E
_0807C6E4:
mov r0, r9
cmp r0, 0
beq _0807C77C
adds r0, r5, 0
adds r1, r4, 0
mov r2, r8
bl CanUseOnTargetWithStatusChecker
lsls r0, 24
cmp r0, 0
beq _0807C6B2
movs r1, 0xF0
lsls r1, 4
ands r1, r6
movs r0, 0x80
lsls r0, 1
cmp r1, r0
beq _0807C78A
movs r0, 0x80
lsls r0, 2
cmp r1, r0
beq _0807C76E
movs r0, 0xC0
lsls r0, 2
cmp r1, r0
bne _0807C720
adds r0, r4, 0
bl HasNegativeStatus
b _0807C774
_0807C720:
movs r0, 0x80
lsls r0, 3
cmp r1, r0
bne _0807C730
adds r0, r4, 0
bl IsSleeping
b _0807C774
_0807C730:
movs r0, 0xC0
lsls r0, 3
cmp r1, r0
bne _0807C75A
ldr r1, [r4, 0x70]
adds r0, r1, 0
adds r0, 0x5C
ldrb r0, [r0]
cmp r0, 0xE
beq _0807C74E
adds r0, r1, 0
adds r0, 0x5D
ldrb r0, [r0]
cmp r0, 0xE
bne _0807C6B2
_0807C74E:
adds r0, r1, 0
adds r0, 0xF5
ldrb r0, [r0]
cmp r0, 0
beq _0807C79E
b _0807C6B2
_0807C75A:
movs r0, 0xA0
lsls r0, 3
cmp r1, r0
bne _0807C79E
adds r0, r4, 0
bl HasNegativeStatus
lsls r0, 24
cmp r0, 0
bne _0807C79E
_0807C76E:
adds r0, r4, 0
bl HasQuarterHPOrLess
_0807C774:
lsls r0, 24
cmp r0, 0
bne _0807C79E
b _0807C6B2
_0807C77C:
movs r0, 0xF0
lsls r0, 4
ands r0, r6
movs r1, 0x80
lsls r1, 1
cmp r0, r1
bne _0807C79E
_0807C78A:
mov r0, r8
movs r1, 0x2
bl GetMoveAccuracy
adds r4, r0, 0
movs r0, 0x64
bl DungeonRandomCapped
cmp r0, r4
bge _0807C6B2
_0807C79E:
adds r0, r7, 0
_0807C7A0:
pop {r3,r4}
mov r8, r3
mov r9, r4
pop {r4-r7}
pop {r1}
bx r1
thumb_func_end CanUseStatusMove
thumb_func_start WeightMove
WeightMove:
push {r4-r7,lr}

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,18 @@ enum MoveFlags
MOVE_FLAG_DISABLED = 1 << 5 // Disabled by an effect like Taunt.
};
enum AccuracyType
{
// Accuracy used for all moves.
ACCURACY_TYPE_GLOBAL,
// Multiplied with the global accuracy for offensive moves (i.e., not status moves).
ACCURACY_TYPE_OFFENSIVE,
// Used by the AI to determine how often to use Spikes.
// Values exist for all other moves, though they seem to be unused.
ACCURACY_TYPE_USE_CHANCE,
NUM_ACCURACY_TYPES
};
struct MoveData
{
u8 *namePointer;
@@ -22,10 +34,8 @@ struct MoveData
// The AI consider certain moves to have different range than they actually do.
/* 0xC */ u8 maxPP;
/* 0xD */ u8 weight;
/* 0xE */ u8 accuracy[2];
// Used by the AI to determine how often to use Spikes.
// Values exist for all other moves, though they seem to be unused.
/* 0x10 */ u8 useChance;
// There are multiple accuracy values. These are define with the AccuracyType enum.
/* 0xE */ u8 accuracy[NUM_ACCURACY_TYPES];
/* 0x11 */ u8 hitCount; // Maximum number of times the move will hit. Used for multi-hit moves like Fury Attack.
u8 unk12;
/* 0x13 */ u8 criticalHitChance;

View File

@@ -5,5 +5,7 @@
// 0x7C580
s32 WeightMoveIfUsable(s32 numPotentialTargets, s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, u32 hasStatusChecker);
// 0x7C648
bool8 CanUseStatusMove(s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool32 hasStatusChecker);
#endif

View File

@@ -11,6 +11,8 @@ u8 GetMoveType(struct PokemonMove *move);
// 0x92B90
u8 GetMoveWeight(struct PokemonMove *move);
s32 GetMovePower(struct PokemonMove *move);
// 0x92BD8
s32 GetMoveAccuracy(struct PokemonMove *move, u32 accuracyType);
// 0x92BF4
u32 GetMoveMaxPP(struct PokemonMove *move);
// 0x92C54

View File

@@ -239,7 +239,7 @@ SECTIONS {
src/dungeon_ai_attack.o(.text);
asm/code_807C4A0.o(.text);
src/dungeon_ai_attack_1.o(.text);
asm/code_807C648.o(.text);
asm/code_807C7AC.o(.text);
src/dungeon_ai_attack_2.o(.text);
asm/code_807CABC.o(.text);
src/targeting_flags.o(.text);

View File

@@ -42,7 +42,6 @@ extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS];
extern bool8 IsMoveUsable_1(struct DungeonEntity*, s32, bool8);
extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8);
extern bool8 IsTargetInLineRange(struct DungeonEntity*, struct DungeonEntity*, s32);
extern bool8 CanUseStatusMove(s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8);
extern s32 WeightMove(struct DungeonEntity*, s32, struct DungeonEntity*, u8);
void DecideAttack(struct DungeonEntity *pokemon)

View File

@@ -2,16 +2,22 @@
#include "dungeon_ai_attack_1.h"
#include "constants/direction.h"
#include "constants/targeting.h"
#include "constants/type.h"
#include "dungeon_ai_targeting_2.h"
#include "dungeon_pokemon_attributes.h"
#include "dungeon_random.h"
#include "moves.h"
#include "position_util.h"
#include "status_checks_1.h"
extern bool8 gCanAttackInDirection[NUM_DIRECTIONS];
extern s32 gPotentialAttackTargetWeights[NUM_DIRECTIONS];
extern u8 gPotentialAttackTargetDirections[NUM_DIRECTIONS];
extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS];
extern bool8 CanUseStatusMove(s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8);
extern s32 WeightMove(struct DungeonEntity*, s32, struct DungeonEntity*, u8);
extern bool8 CanUseOnTargetWithStatusChecker(struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*);
s32 WeightMoveIfUsable(s32 numPotentialTargets, s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool32 hasStatusChecker)
{
@@ -42,103 +48,128 @@ s32 WeightMoveIfUsable(s32 numPotentialTargets, s32 targetingFlags, struct Dunge
return numPotentialTargets;
}
// NAKED
// s32 WeightMoveIfUsable(s32 numPotentialTargets, s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool8 hasStatusChecker)
// {
// asm_unified("push {r4-r7,lr}\n"
// "mov r7, r10\n"
// "mov r6, r9\n"
// "mov r5, r8\n"
// "push {r5-r7}\n"
// "sub sp, 0x4\n"
// "adds r6, r0, 0\n"
// "adds r5, r2, 0\n"
// "adds r7, r3, 0\n"
// "ldr r0, [sp, 0x28]\n"
// "lsls r1, 16\n"
// "asrs r1, 16\n"
// "mov r9, r1\n"
// "lsls r0, 24\n"
// "lsrs r0, 24\n"
// "mov r10, r0\n"
// "ldr r2, [r5, 0x70]\n"
// "ldr r1, [r5, 0x4]\n"
// "ldr r0, [r7, 0x4]\n"
// "cmp r1, r0\n"
// "beq _0807C5BC\n"
// "movs r0, 0xF0\n"
// "mov r1, r9\n"
// "ands r0, r1\n"
// "cmp r0, 0x30\n"
// "beq _0807C5BC\n"
// "cmp r0, 0x60\n"
// "beq _0807C5BC\n"
// "cmp r0, 0x70\n"
// "bne _0807C5C4\n"
// "_0807C5BC:\n"
// "adds r0, r2, 0\n"
// "adds r0, 0x46\n"
// "ldrb r4, [r0]\n"
// "b _0807C5CE\n"
// "_0807C5C4:\n"
// "adds r0, r5, 0x4\n"
// "adds r1, r7, 0x4\n"
// "bl CalculateFacingDir\n"
// "adds r4, r0, 0\n"
// "_0807C5CE:\n"
// "ldr r0, _0807C638\n"
// "adds r0, r4\n"
// "mov r8, r0\n"
// "ldrb r0, [r0]\n"
// "cmp r0, 0\n"
// "bne _0807C624\n"
// "mov r0, r10\n"
// "str r0, [sp]\n"
// "mov r0, r9\n"
// "adds r1, r5, 0\n"
// "adds r2, r7, 0\n"
// "ldr r3, [sp, 0x24]\n"
// "bl CanUseStatusMove\n"
// "lsls r0, 24\n"
// "cmp r0, 0\n"
// "beq _0807C624\n"
// "movs r0, 0x1\n"
// "mov r1, r8\n"
// "strb r0, [r1]\n"
// "ldr r0, _0807C63C\n"
// "adds r0, r6, r0\n"
// "strb r4, [r0]\n"
// "adds r0, r5, 0\n"
// "ldr r1, [sp, 0x24]\n"
// "bl GetMoveTypeForPokemon\n"
// "adds r3, r0, 0\n"
// "lsls r3, 24\n"
// "lsrs r3, 24\n"
// "adds r0, r5, 0\n"
// "mov r1, r9\n"
// "adds r2, r7, 0\n"
// "bl WeightMove\n"
// "ldr r1, _0807C640\n"
// "lsls r2, r6, 2\n"
// "adds r1, r2, r1\n"
// "str r0, [r1]\n"
// "ldr r0, _0807C644\n"
// "adds r2, r0\n"
// "str r7, [r2]\n"
// "adds r6, 0x1\n"
// "_0807C624:\n"
// "adds r0, r6, 0\n"
// "add sp, 0x4\n"
// "pop {r3-r5}\n"
// "mov r8, r3\n"
// "mov r9, r4\n"
// "mov r10, r5\n"
// "pop {r4-r7}\n"
// "pop {r1}\n"
// "bx r1\n"
// ".align 2, 0\n"
// "_0807C638: .4byte gCanAttackInDirection\n"
// "_0807C63C: .4byte gPotentialAttackTargetDirections\n"
// "_0807C640: .4byte gPotentialAttackTargetWeights\n"
// "_0807C644: .4byte gPotentialTargets");
// }
bool8 CanUseStatusMove(s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool32 hasStatusChecker)
{
struct DungeonEntityData *targetData;
s32 targetingFlags2 = (s16) targetingFlags;
bool8 hasStatusChecker2 = hasStatusChecker;
bool8 hasTarget = FALSE;
u32 categoryTargetingFlags = targetingFlags2 & 0xF;
u32 *categoryTargetingFlags2 = &categoryTargetingFlags; // Fixes a regswap.
if (*categoryTargetingFlags2 == TARGETING_FLAG_TARGET_OTHER)
{
if (CanTarget(user, target, FALSE, TRUE) == TARGET_CAPABILITY_CAN_TARGET)
{
hasTarget = TRUE;
}
}
else if (categoryTargetingFlags == TARGETING_FLAG_HEAL_TEAM)
{
goto checkCanTarget;
}
else if (categoryTargetingFlags == TARGETING_FLAG_LONG_RANGE)
{
targetData = target->entityData;
goto checkThirdParty;
}
else if (categoryTargetingFlags == TARGETING_FLAG_ATTACK_ALL)
{
targetData = target->entityData;
if (user == target)
{
goto returnFalse;
}
checkThirdParty:
hasTarget = TRUE;
if (targetData->shopkeeperMode == SHOPKEEPER_FRIENDLY ||
targetData->clientType == CLIENT_TYPE_DONT_MOVE ||
targetData->clientType == CLIENT_TYPE_CLIENT)
{
returnFalse:
return FALSE;
}
}
else if (categoryTargetingFlags == TARGETING_FLAG_BOOST_TEAM)
{
if (user == target)
{
goto returnFalse;
}
checkCanTarget:
if (CanTarget(user, target, FALSE, TRUE) == TARGET_CAPABILITY_CANNOT_ATTACK)
{
hasTarget = TRUE;
}
}
else if ((u16) (categoryTargetingFlags - 3) <= 1) // categoryTargetingFlags == TARGETING_FLAG_ITEM
{
hasTarget = TRUE;
}
if (hasTarget)
{
if (hasStatusChecker2)
{
if (!CanUseOnTargetWithStatusChecker(user, target, move))
{
goto returnFalse;
}
if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_SET_TRAP)
{
goto rollMoveUseChance;
}
else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_HEAL_HP)
{
if (!HasQuarterHPOrLess(target))
{
if (*categoryTargetingFlags2);
goto returnFalse;
}
}
else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_HEAL_STATUS)
{
if (!HasNegativeStatus(target))
{
if (*categoryTargetingFlags2); // Flips the conditional.
goto returnFalse;
}
}
else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_DREAM_EATER)
{
if (!IsSleeping(target))
{
if (*categoryTargetingFlags2); // Flips the conditional.
goto returnFalse;
}
}
else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_EXPOSE)
{
targetData = target->entityData;
if ((targetData->type1 != TYPE_GHOST && targetData->type2 != TYPE_GHOST) || targetData->exposedStatus)
{
if (*categoryTargetingFlags2); // Flips the conditional.
goto returnFalse;
}
}
else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_HEAL_ALL)
{
if (!HasNegativeStatus(target) && !HasQuarterHPOrLess(target))
{
if (*categoryTargetingFlags2); // Flips the conditional.
goto returnFalse;
}
}
}
else if ((targetingFlags2 & 0xF00) == TARGETING_FLAG_SET_TRAP)
{
s32 useChance;
rollMoveUseChance:
useChance = GetMoveAccuracy(move, ACCURACY_TYPE_USE_CHANCE);
if (DungeonRandomCapped(100) >= useChance)
{
goto returnFalse;
}
}
}
return hasTarget;
}

View File

@@ -251,9 +251,9 @@ s32 GetMovePower(struct PokemonMove *move)
return gMovesData[move->moveID].power;
}
u8 GetMoveAccuracy(struct PokemonMove *move, u32 r1)
s32 GetMoveAccuracy(struct PokemonMove *move, u32 accuracyType)
{
return gMovesData[move->moveID].accuracy[r1];
return gMovesData[move->moveID].accuracy[accuracyType];
}
u32 GetMoveMaxPP(struct PokemonMove *move)

View File

@@ -490,9 +490,9 @@ string generate_move_data_text(Json data) {
<< read_json_binary(data_entry["aiTargetingFlags"], 2)
<< read_json_int(data_entry["maxPP"], 1)
<< read_json_int(data_entry["weight"], 1)
<< read_json_int(data_entry["accuracy1"], 1)
<< read_json_int(data_entry["accuracy2"], 1)
<< read_json_int(data_entry["useChance"], 1)
<< read_json_int(data_entry["accuracyGlobal"], 1)
<< read_json_int(data_entry["accuracyOffensive"], 1)
<< read_json_int(data_entry["accuracyUseChance"], 1)
<< read_json_int(data_entry["hitCount"], 1)
<< read_json_int(data_entry["unk12"], 1)
<< read_json_int(data_entry["criticalHitChance"], 1)