Decomped CanUseOnSelfWithStatusChecker()

This commit is contained in:
AnonymousRandomPerson 2022-02-20 12:51:18 -05:00
parent 3555fb7c94
commit 96372eb336
15 changed files with 26172 additions and 26587 deletions

View File

@ -2524,7 +2524,7 @@ sub_80414C0:
bne _080414DC
adds r0, r5, 0
bl GetMapEntityForDungeonEntity
bl IsTileWater
bl IsTileGround
lsls r0, 24
cmp r0, 0
bne _080414F2

View File

@ -3374,8 +3374,8 @@ _0804AF18: .4byte gDungeonGlobalData
_0804AF1C: .4byte 0x000135cc
thumb_func_end sub_804AE84
thumb_func_start IsTileWater
IsTileWater:
thumb_func_start IsTileGround
IsTileGround:
push {r4,r5,lr}
adds r4, r0, 0
movs r5, 0
@ -3417,7 +3417,7 @@ _0804AF5E:
_0804AF68: .4byte gDungeonWaterType
_0804AF6C: .4byte gDungeonGlobalData
_0804AF70: .4byte 0x00003a0e
thumb_func_end IsTileWater
thumb_func_end IsTileGround
thumb_func_start IsWaterTileset
IsWaterTileset:

View File

@ -911,7 +911,7 @@ sub_8057788:
adds r0, r4, 0
bl GetMapEntityForDungeonEntity
adds r5, r0, 0
bl IsTileWater
bl IsTileGround
lsls r0, 24
cmp r0, 0
beq _080577BA

File diff suppressed because it is too large Load Diff

25559
asm/code_805CEB8.s Normal file

File diff suppressed because it is too large Load Diff

View File

@ -326,7 +326,7 @@ _0807C6E4:
adds r0, r5, 0
adds r1, r4, 0
mov r2, r8
bl CanUseWithStatusChecker_2
bl CanUseOnTargetWithStatusChecker
lsls r0, 24
cmp r0, 0
beq _0807C6B2

View File

@ -830,52 +830,3 @@ gUnknown_80F55BC: @ 80F55BC
.global gUnknown_80F55EC
gUnknown_80F55EC: @ 80F55EC
.incbin "baserom.gba", 0xF55EC, 0x30
.global gDungeonCamouflageTypes
gDungeonCamouflageTypes: @ 80F561C
.incbin "baserom.gba", 0xF561C, 0x4C
.global gDungeonMusic
gDungeonMusic: @ 80F5668
.incbin "baserom.gba", 0xF5668, 0x98
.global gUnknown_80F5700
gUnknown_80F5700: @ 80F5700
.incbin "baserom.gba", 0xF5700, 0xCA
.global gUnknown_80F57CA
gUnknown_80F57CA: @ 80F57CA
@ replacing .incbin "baserom.gba", 0x000f57ca, 0x2
.byte 0x0a, 0x00
.global gUnknown_80F57CC
gUnknown_80F57CC: @ 80F57CC
@ replacing .incbin "baserom.gba", 0x000f57cc, 0x2
.byte 0x14, 0x00
.global gUnknown_80F57CE
gUnknown_80F57CE: @ 80F57CE
@ replacing .incbin "baserom.gba", 0x000f57ce, 0x2
.byte 0x14, 0x00
.global gUnknown_80F57D0
gUnknown_80F57D0: @ 80F57D0
@ replacing .incbin "baserom.gba", 0x000f57d0, 0x2
.byte 0x14, 0x00
.global gUnknown_80F57D2
gUnknown_80F57D2: @ 80F57D2
@ replacing .incbin "baserom.gba", 0x000f57d2, 0x2
.byte 0x0a, 0x00
.global gUnknown_80F57D4
gUnknown_80F57D4: @ 80F57D4
.incbin "baserom.gba", 0xF57D4, 0x120
.global gUnknown_80F58F4
gUnknown_80F58F4: @ 80F58F4
.incbin "baserom.gba", 0xF58F4, 0x84
.global gUnknown_80F5978
gUnknown_80F5978: @ 80F5978
.incbin "baserom.gba", 0xF5978, 0x4C

46
data/data_80F5668.s Normal file
View File

@ -0,0 +1,46 @@
.section .rodata
.global gDungeonMusic
gDungeonMusic: @ 80F5668
.incbin "baserom.gba", 0xF5668, 0x98
.global gUnknown_80F5700
gUnknown_80F5700: @ 80F5700
.incbin "baserom.gba", 0xF5700, 0xCA
.global gUnknown_80F57CA
gUnknown_80F57CA: @ 80F57CA
@ replacing .incbin "baserom.gba", 0x000f57ca, 0x2
.byte 0x0a, 0x00
.global gUnknown_80F57CC
gUnknown_80F57CC: @ 80F57CC
@ replacing .incbin "baserom.gba", 0x000f57cc, 0x2
.byte 0x14, 0x00
.global gUnknown_80F57CE
gUnknown_80F57CE: @ 80F57CE
@ replacing .incbin "baserom.gba", 0x000f57ce, 0x2
.byte 0x14, 0x00
.global gUnknown_80F57D0
gUnknown_80F57D0: @ 80F57D0
@ replacing .incbin "baserom.gba", 0x000f57d0, 0x2
.byte 0x14, 0x00
.global gUnknown_80F57D2
gUnknown_80F57D2: @ 80F57D2
@ replacing .incbin "baserom.gba", 0x000f57d2, 0x2
.byte 0x0a, 0x00
.global gUnknown_80F57D4
gUnknown_80F57D4: @ 80F57D4
.incbin "baserom.gba", 0xF57D4, 0x120
.global gUnknown_80F58F4
gUnknown_80F58F4: @ 80F58F4
.incbin "baserom.gba", 0xF58F4, 0x84
.global gUnknown_80F5978
gUnknown_80F5978: @ 80F5978
.incbin "baserom.gba", 0xF5978, 0x4C

View File

@ -4,7 +4,7 @@
#define WEATHER_CLEAR 0
#define WEATHER_SUNNY 1
#define WEATHER_SANDSTORM 2
#define WEATHER_CLOUDY` 3
#define WEATHER_CLOUDY 3
#define WEATHER_RAIN 4
#define WEATHER_HAIL 5
#define WEATHER_FOG 6

View File

@ -6,6 +6,9 @@
#include "item.h"
#include "position.h"
#define MAX_STAT_STAGE 20
#define MAX_MOVEMENT_SPEED 4
#define MAX_STOCKPILE_COUNT 3
#define NUM_SPEED_TURN_COUNTERS 5
struct DungeonActionContainer

10
include/status_checker.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef GUARD_STATUS_CHECKER_H
#define GUARD_STATUS_CHECKER_H
#include "constants/move.h"
#include "dungeon_entity.h"
// 0x5C498
bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move);
#endif

View File

@ -207,6 +207,8 @@ SECTIONS {
asm/code_8057144.o(.text);
src/code_8057824.o(.text);
asm/code_8057824.o(.text);
src/status_checker.o(.text);
asm/code_805CEB8.o(.text);
src/targeting.o(.text);
asm/code_8069E0C.o(.text);
src/code_806CD90.o(.text);
@ -408,6 +410,8 @@ SECTIONS {
data/data_80F4DB4.o(.rodata);
src/dungeon_ai_attack.o(.rodata);
data/data_80F4E2C.o(.rodata);
src/status_checker.o(.rodata);
data/data_80F5668.o(.rodata);
src/dungeon_pokemon_attributes.o(.rodata);
data/data_80F59C8.o(.rodata);
src/charge_move.o(.rodata);

View File

@ -22,6 +22,7 @@
#include "dungeon_visibility.h"
#include "moves.h"
#include "position_util.h"
#include "status_checker.h"
#include "status_checks.h"
#include "targeting.h"
#include "targeting_flags.h"
@ -38,7 +39,6 @@ extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS];
extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8);
extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8);
extern bool8 CanUseWithStatusChecker(struct DungeonEntity*, struct PokemonMove*);
extern bool8 CanAttackInFront(struct DungeonEntity*, s32);
extern s32 WeightMoveIfUsable(s32, s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8);
extern bool8 IsTargetInLineRange(struct DungeonEntity*, struct DungeonEntity*, s32);
@ -349,7 +349,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn
hasStatusChecker = HasIQSkill(pokemon, IQ_SKILL_STATUS_CHECKER);
moveTargetResults->moveUsable = FALSE;
if ((pokemonData->volatileStatus == VOLATILE_STATUS_TAUNTED && !MoveDealsDirectDamage(move)) ||
(hasStatusChecker && !CanUseWithStatusChecker(pokemon, move)))
(hasStatusChecker && !CanUseOnSelfWithStatusChecker(pokemon, move)))
{
return 1;
}

View File

@ -185,7 +185,7 @@ u32 EvaluateItem(struct DungeonEntity *targetPokemon, struct ItemSlot *item, u32
}
break;
case ITEM_ID_QUICK_SEED:
if (targetPokemon->entityData->movementSpeed <= 3)
if (targetPokemon->entityData->movementSpeed < MAX_MOVEMENT_SPEED)
{
if (CanTargetAdjacentPokemon(targetPokemon))
{

539
src/status_checker.c Normal file
View File

@ -0,0 +1,539 @@
#include "global.h"
#include "status_checker.h"
#include "constants/move_id.h"
#include "constants/status.h"
#include "constants/type.h"
#include "constants/weather.h"
#include "dungeon_global_data.h"
#include "dungeon_pokemon_attributes.h"
#include "dungeon_util.h"
#include "dungeon_visibility.h"
#include "map.h"
#include "number_util.h"
#include "status_checks_1.h"
// Array indices correspond to the current dungeon tileset.
const u8 gDungeonCamouflageTypes[76] = {
TYPE_WATER,
TYPE_GRASS,
TYPE_ROCK,
TYPE_ROCK,
TYPE_ROCK,
TYPE_ROCK,
TYPE_ROCK,
TYPE_ROCK,
TYPE_NORMAL,
TYPE_ROCK,
TYPE_GRASS,
TYPE_GROUND,
TYPE_NORMAL,
TYPE_NORMAL,
TYPE_GRASS,
TYPE_ICE,
TYPE_NORMAL,
TYPE_ROCK,
TYPE_ICE,
TYPE_ICE,
TYPE_GRASS,
TYPE_GROUND,
TYPE_ROCK,
TYPE_NORMAL,
TYPE_ICE,
TYPE_GRASS,
TYPE_GRASS,
TYPE_NORMAL,
TYPE_ROCK,
TYPE_GRASS,
TYPE_ROCK,
TYPE_ROCK,
TYPE_GRASS,
TYPE_GRASS,
TYPE_ROCK,
TYPE_NORMAL,
TYPE_ICE,
TYPE_ROCK,
TYPE_ROCK,
TYPE_ROCK,
TYPE_ROCK,
TYPE_GRASS,
TYPE_ROCK,
TYPE_ROCK,
TYPE_GROUND,
TYPE_NORMAL,
TYPE_ROCK,
TYPE_ICE,
TYPE_ROCK,
TYPE_WATER,
TYPE_GRASS,
TYPE_GRASS,
TYPE_GROUND,
TYPE_WATER,
TYPE_ROCK,
TYPE_ROCK,
TYPE_GRASS,
TYPE_NORMAL,
TYPE_NORMAL,
TYPE_ROCK,
TYPE_GRASS,
TYPE_ROCK,
TYPE_GRASS,
TYPE_GRASS,
TYPE_ROCK,
TYPE_GRASS,
TYPE_ROCK,
TYPE_ROCK,
TYPE_NORMAL,
TYPE_NORMAL,
TYPE_ROCK,
TYPE_NORMAL,
TYPE_ICE,
TYPE_WATER,
TYPE_WATER,
TYPE_ROCK
};
extern bool8 IsBossBattle();
extern u8 GetWeather(struct DungeonEntity*);
extern bool8 HasQuarterHPOrLess(struct DungeonEntity*);
extern bool8 IsTileGround(struct MapTile*);
extern bool8 CanLayTrap(struct Position*);
bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move)
{
struct DungeonEntityData *pokemonData = pokemon->entityData;
switch (move->moveID)
{
case MOVE_HAIL:
if (GetWeather(pokemon) == WEATHER_HAIL)
{
return FALSE;
}
break;
case MOVE_RAGE:
if (pokemonData->chargingStatus == CHARGING_STATUS_RAGE)
{
return FALSE;
}
break;
case MOVE_COUNTER:
case MOVE_PURSUIT:
if (pokemonData->protectionStatus == PROTECTION_STATUS_COUNTER)
{
return FALSE;
}
break;
case MOVE_MIRROR_MOVE:
if (pokemonData->protectionStatus == PROTECTION_STATUS_MIRROR_MOVE)
{
return FALSE;
}
break;
case MOVE_HOWL:
case MOVE_MEDITATE:
case MOVE_SHARPEN:
if (pokemonData->attackStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_BELLY_DRUM:
if (pokemonData->attackStage >= MAX_STAT_STAGE || RoundUpFixedPoint(pokemonData->belly) <= 0)
{
return FALSE;
}
break;
case MOVE_ACID_ARMOR:
case MOVE_BARRIER:
case MOVE_DEFENSE_CURL:
case MOVE_HARDEN:
case MOVE_IRON_DEFENSE:
case MOVE_WITHDRAW:
if (pokemonData->defenseStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_BIDE:
case MOVE_REVENGE:
if (pokemonData->chargingStatus == CHARGING_STATUS_BIDE)
{
return FALSE;
}
break;
case MOVE_AGILITY:
{
u32 r1;
#ifndef NONMATCHING
asm("":"=r"(r1));
#else
r1 = 0;
#endif
if (pokemon->entityData->movementSpeed >= MAX_MOVEMENT_SPEED)
{
r1 = !r1;
return FALSE;
}
break;
}
case MOVE_LOCK_ON:
case MOVE_MIND_READER:
if (pokemonData->moveStatus == MOVE_STATUS_SURE_SHOT)
{
return FALSE;
}
break;
case MOVE_COSMIC_POWER:
if (pokemonData->defenseStage >= MAX_STAT_STAGE && pokemonData->specialDefenseStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_ENDURE:
if (pokemonData->protectionStatus == PROTECTION_STATUS_ENDURE)
{
return FALSE;
}
break;
case MOVE_CHARGE:
if (pokemonData->chargingStatus == CHARGING_STATUS_CHARGE)
{
return FALSE;
}
break;
case MOVE_MIST:
if (pokemonData->protectionStatus == PROTECTION_STATUS_MIST)
{
return FALSE;
}
break;
case MOVE_LIGHT_SCREEN:
if (pokemonData->protectionStatus == PROTECTION_STATUS_LIGHT_SCREEN)
{
return FALSE;
}
break;
case MOVE_MINIMIZE:
if (pokemonData->evasionStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_INGRAIN:
if (pokemonData->immobilizeStatus == IMMOBILIZE_STATUS_INGRAIN || pokemonData->maxHP / 2 < pokemonData->HP)
{
return FALSE;
}
break;
case MOVE_SWALLOW:
if (pokemonData->maxHP <= pokemonData->HP || pokemonData->stockpileCount == 0)
{
return FALSE;
}
break;
case MOVE_SPIT_UP:
if (pokemonData->stockpileCount == 0)
{
return FALSE;
}
break;
case MOVE_DOOM_DESIRE:
case MOVE_FUTURE_SIGHT:
if (pokemonData->moveStatus == MOVE_STATUS_SET_DAMAGE)
{
return FALSE;
}
break;
case MOVE_BULK_UP:
if (pokemonData->attackStage >= MAX_STAT_STAGE && pokemonData->defenseStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_CAMOUFLAGE:
if (HasType(pokemon, gDungeonCamouflageTypes[gDungeonGlobalData->tileset]))
{
return FALSE;
}
break;
case MOVE_TAIL_GLOW:
if (pokemonData->specialAttackStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_DESTINY_BOND:
if (pokemonData->linkedStatus == LINKED_STATUS_DESTINY_BOND)
{
return FALSE;
}
break;
case MOVE_MIRROR_COAT:
if (pokemonData->protectionStatus == PROTECTION_STATUS_MIRROR_COAT)
{
return FALSE;
}
break;
case MOVE_REFLECT:
if (pokemonData->protectionStatus == PROTECTION_STATUS_REFLECT)
{
return FALSE;
}
break;
case MOVE_DRAGON_DANCE:
if (pokemonData->attackStage >= MAX_STAT_STAGE && pokemon->entityData->movementSpeed >= MAX_MOVEMENT_SPEED)
{
return FALSE;
}
break;
case MOVE_MAGIC_COAT:
if (pokemonData->protectionStatus == PROTECTION_STATUS_MAGIC_COAT)
{
return FALSE;
}
break;
case MOVE_DETECT:
case MOVE_PROTECT:
if (pokemonData->protectionStatus == PROTECTION_STATUS_PROTECT)
{
return FALSE;
}
break;
case MOVE_RAIN_DANCE:
if (GetWeather(pokemon) == WEATHER_RAIN)
{
return FALSE;
}
break;
case MOVE_SANDSTORM:
if (GetWeather(pokemon) == WEATHER_SANDSTORM)
{
return FALSE;
}
break;
case MOVE_SUNNY_DAY:
if (GetWeather(pokemon) == WEATHER_SUNNY)
{
return FALSE;
}
break;
case MOVE_SAFEGUARD:
if (pokemonData->protectionStatus == PROTECTION_STATUS_SAFEGUARD)
{
return FALSE;
}
break;
case MOVE_INVISIFY:
if (pokemonData->transformStatus == TRANSFORM_STATUS_INVISIBLE)
{
return FALSE;
}
break;
case MOVE_FOCUS_ENERGY:
if (pokemonData->moveStatus == MOVE_STATUS_FOCUS_ENERGY)
{
return FALSE;
}
break;
case MOVE_TAKEAWAY:
if (pokemonData->heldItem.itemFlags & ITEM_FLAG_EXISTS)
{
return FALSE;
}
break;
case MOVE_REST:
if (!HasQuarterHPOrLess(pokemon) && !HasNegativeStatus(pokemon))
{
return FALSE;
}
break;
case MOVE_DIVE:
if (IsTileGround(GetMapEntityForDungeonEntity(pokemon)))
{
return FALSE;
}
break;
case MOVE_DIG:
{
struct MapTile *tile = GetMapEntityForDungeonEntity(pokemon);
if (!IsTileGround(tile) || (tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)) != TILE_TYPE_FLOOR)
{
return FALSE;
}
break;
}
case MOVE_TRAP_BUSTER:
{
struct DungeonEntity *mapObject = GetMapEntityForDungeonEntity(pokemon)->mapObject;
if (mapObject == NULL || GetEntityType(mapObject) != ENTITY_TRAP)
{
return FALSE;
}
break;
}
case MOVE_MUD_SPORT:
if (gDungeonGlobalData->mudSportTurnsLeft > 0)
{
return FALSE;
}
break;
case MOVE_WATER_SPORT:
if (gDungeonGlobalData->waterSportTurnsLeft > 0)
{
return FALSE;
}
break;
case MOVE_GRUDGE:
if (pokemonData->grudgeStatus)
{
return FALSE;
}
break;
case MOVE_DECOY_MAKER:
case MOVE_FOLLOW_ME:
case MOVE_SUBSTITUTE:
if (gDungeonGlobalData->decoyActive)
{
return FALSE;
}
break;
case MOVE_STOCKPILE:
if (pokemonData->stockpileCount >= MAX_STOCKPILE_COUNT)
{
return FALSE;
}
break;
case MOVE_CLEANSE:
if (pokemonData->heldItem.itemFlags & ITEM_FLAG_EXISTS &&
!(pokemonData->heldItem.itemFlags & ITEM_FLAG_STICKY))
{
return FALSE;
}
break;
case MOVE_DOUBLE_TEAM:
if (pokemonData->evasionStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_GROWTH:
if (pokemonData->specialAttackStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_SWORDS_DANCE:
if (pokemonData->attackStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_WISH:
if (pokemonData->isEnemy || pokemonData->protectionStatus == PROTECTION_STATUS_WISH)
{
return FALSE;
}
break;
case MOVE_TRANSFORM:
if (pokemonData->transformStatus == TRANSFORM_STATUS_TRANSFORMED)
{
return FALSE;
}
break;
case MOVE_SPIKES:
if (!CanLayTrap(&pokemon->posWorld))
{
return FALSE;
}
break;
case MOVE_CALM_MIND:
if (pokemonData->specialAttackStage < MAX_STAT_STAGE)
{
break;
}
case MOVE_AMNESIA:
if (pokemonData->specialDefenseStage >= MAX_STAT_STAGE)
{
return FALSE;
}
break;
case MOVE_SNATCH:
if (pokemonData->waitingStatus == WAITING_STATUS_SNATCH)
{
return FALSE;
}
break;
case MOVE_BEAT_UP:
case MOVE_BLOWBACK:
case MOVE_HURL:
case MOVE_MEMENTO:
case MOVE_ROAR:
case MOVE_STAY_AWAY:
case MOVE_SWITCHER:
case MOVE_TELEPORT:
case MOVE_VITAL_THROW:
case MOVE_WARP:
case MOVE_WHIRLWIND:
if (IsBossBattle())
{
return FALSE;
}
break;
case MOVE_CONVERSION_2:
if (pokemonData->protectionStatus == PROTECTION_STATUS_CONVERSION_2)
{
return FALSE;
}
break;
case MOVE_HELPING_HAND:
if (pokemonData->isEnemy)
{
s32 i;
for (i = 0; i < DUNGEON_MAX_WILD_POKEMON; i++)
{
struct DungeonEntity *target = gDungeonGlobalData->wildPokemon[i];
if (EntityExists(target) && target != pokemon && CanSee(pokemon, target))
{
if (target->entityData->attackStage >= MAX_STAT_STAGE)
{
continue;
}
if (target->entityData->specialAttackStage < MAX_STAT_STAGE)
{
break;
}
}
}
if (i == DUNGEON_MAX_WILD_POKEMON)
{
return FALSE;
}
break;
}
else
{
s32 i;
for (i = 0; i < MAX_TEAM_MEMBERS; i++)
{
struct DungeonEntity *target = gDungeonGlobalData->teamPokemon[i];
if (EntityExists(target) && target != pokemon && CanSee(pokemon, target))
{
if (target->entityData->attackStage >= MAX_STAT_STAGE)
{
continue;
}
if (target->entityData->specialAttackStage < MAX_STAT_STAGE)
{
break;
}
}
}
if (i == MAX_TEAM_MEMBERS)
{
return FALSE;
}
break;
}
}
return TRUE;
}