From 96372eb336d21e5da66246983e0522212f370bdf Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 12:51:18 -0500 Subject: Decomped CanUseOnSelfWithStatusChecker() --- src/dungeon_ai_attack.c | 4 +- src/dungeon_ai_item_weight.c | 2 +- src/status_checker.c | 539 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 542 insertions(+), 3 deletions(-) create mode 100644 src/status_checker.c (limited to 'src') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 30e5d3a..a275081 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -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; } diff --git a/src/dungeon_ai_item_weight.c b/src/dungeon_ai_item_weight.c index 0fe019f..5006970 100644 --- a/src/dungeon_ai_item_weight.c +++ b/src/dungeon_ai_item_weight.c @@ -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)) { diff --git a/src/status_checker.c b/src/status_checker.c new file mode 100644 index 0000000..379082f --- /dev/null +++ b/src/status_checker.c @@ -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; +} -- cgit v1.2.3 From 60a19d681cda14c4ebeab5d18a98e3b07a5e93a3 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 21:59:07 -0500 Subject: Decomped GetMapTile_2 --- src/code_8040094.c | 5 ++--- src/code_80521D0_1.c | 6 +++--- src/code_8057824_1.c | 2 +- src/dungeon_ai_attack.c | 6 +++--- src/dungeon_ai_attack_1.c | 2 +- src/dungeon_ai_item_weight.c | 2 +- src/dungeon_ai_items.c | 2 +- src/dungeon_ai_movement.c | 4 ++-- src/dungeon_capabilities_1.c | 4 ++-- src/dungeon_map_access.c | 20 ++++++++++++++++---- src/dungeon_range.c | 2 +- src/dungeon_util.c | 10 ++++------ src/status_checker.c | 6 +++--- 13 files changed, 40 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/code_8040094.c b/src/code_8040094.c index c0e7eac..f7374e3 100644 --- a/src/code_8040094.c +++ b/src/code_8040094.c @@ -3,6 +3,7 @@ #include "code_80521D0.h" #include "dungeon_entity.h" #include "dungeon_global_data.h" +#include "dungeon_map_access.h" #include "file_system.h" #include "play_time.h" @@ -26,8 +27,6 @@ extern void sub_8040A84(); extern const char *gUnknown_80FD040; // It became brighter on the floor -extern struct MapTile *GetMapEntity(u32, u32); - // Luminous Orb??? void HandleLuminousOrbAction(struct DungeonEntity *param_1) { @@ -41,7 +40,7 @@ void HandleLuminousOrbAction(struct DungeonEntity *param_1) { for(XCoord = 0; XCoord < DUNGEON_MAX_SIZE_X; XCoord++) { - mapTile = GetMapEntity(XCoord, YCoord); + mapTile = GetMapTile_2(XCoord, YCoord); mapTile->unk4 = mapTile->unk4 | 1; } } diff --git a/src/code_80521D0_1.c b/src/code_80521D0_1.c index 2b23a14..53f5586 100644 --- a/src/code_80521D0_1.c +++ b/src/code_80521D0_1.c @@ -3,6 +3,7 @@ #include "constants/friend_area.h" #include "dungeon_global_data.h" #include "dungeon_entity.h" +#include "dungeon_map_access.h" #include "dungeon_random.h" #include "dungeon_util.h" #include "friend_area.h" @@ -138,7 +139,6 @@ extern void sub_8049ED4(); extern void sub_8040A84(); extern void sub_8086A54(struct DungeonEntity *); -extern struct MapTile *GetMapEntity(u32, u32); extern void sub_806BFC0(struct DungeonEntityData *, u32); void sub_808BBA8(struct DungeonEntity *param_1) @@ -207,7 +207,7 @@ void sub_808BCE4(void) { struct MapTile *puVar1; - puVar1 = GetMapEntity(gDungeonGlobalData->unkE23C, gDungeonGlobalData->unkE23E); + puVar1 = GetMapTile_2(gDungeonGlobalData->unkE23C, gDungeonGlobalData->unkE23E); puVar1->tileType &= ~(TILE_TYPE_FLOOR | TILE_TYPE_LIQUID); puVar1->tileType |= TILE_TYPE_MAP_EDGE; puVar1->tileType &= ~TILE_TYPE_STAIRS; @@ -221,7 +221,7 @@ void sub_808BD38(void) { struct MapTile *puVar1; - puVar1 = GetMapEntity(gDungeonGlobalData->unkE23C, gDungeonGlobalData->unkE23E); + puVar1 = GetMapTile_2(gDungeonGlobalData->unkE23C, gDungeonGlobalData->unkE23E); puVar1->tileType &= ~(TILE_TYPE_FLOOR | TILE_TYPE_LIQUID); puVar1->tileType |= TILE_TYPE_FLOOR; puVar1->tileType &= ~TILE_TYPE_MAP_EDGE; diff --git a/src/code_8057824_1.c b/src/code_8057824_1.c index f3a7db2..0d48f71 100644 --- a/src/code_8057824_1.c +++ b/src/code_8057824_1.c @@ -3318,7 +3318,7 @@ void sub_808B1CC(u8 r0) "\tldrsh r0, [r0, r2]\n" "\tmovs r3, 0x2\n" "\tldrsh r1, [r5, r3]\n" - "\tbl GetMapEntity\n" + "\tbl GetMapTile_2\n" "\tldrh r2, [r0]\n" "\tmovs r3, 0x80\n" "\tlsls r3, 2\n" diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index a275081..092bab5 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -377,7 +377,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn { // Double assignment to fix a regswap. s16 rangeTargetingFlags = rangeTargetingFlags2 = targetingFlags & 0xF0; - struct MapTile *adjacentTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[i].x, + struct MapTile *adjacentTile = GetMapTile_1(pokemon->posWorld.x + gAdjacentTileOffsets[i].x, pokemon->posWorld.y + gAdjacentTileOffsets[i].y); struct DungeonEntity *adjacentPokemon = adjacentTile->pokemon; if (adjacentPokemon != NULL && GetEntityType(adjacentPokemon) == ENTITY_POKEMON) @@ -411,7 +411,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn { for (i = 0; i < NUM_DIRECTIONS; i++) { - struct MapTile *targetTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[i].x, + struct MapTile *targetTile = GetMapTile_1(pokemon->posWorld.x + gAdjacentTileOffsets[i].x, pokemon->posWorld.y + gAdjacentTileOffsets[i].y); if (CanAttackInFront(pokemon, i)) { @@ -425,7 +425,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn continue; } } - targetTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[i].x * 2, + targetTile = GetMapTile_1(pokemon->posWorld.x + gAdjacentTileOffsets[i].x * 2, pokemon->posWorld.y + gAdjacentTileOffsets[i].y * 2); targetPokemon = targetTile->pokemon; if (targetPokemon != NULL && GetEntityType(targetPokemon) == ENTITY_POKEMON) diff --git a/src/dungeon_ai_attack_1.c b/src/dungeon_ai_attack_1.c index 8a186ea..641bc8c 100644 --- a/src/dungeon_ai_attack_1.c +++ b/src/dungeon_ai_attack_1.c @@ -57,7 +57,7 @@ bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity break; } while (0); // Extra label needed to swap branch locations in ASM. - mapTile = GetMapTileAtPosition(currentPosX, currentPosY); + mapTile = GetMapTile_1(currentPosX, currentPosY); if (!(mapTile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) { break; diff --git a/src/dungeon_ai_item_weight.c b/src/dungeon_ai_item_weight.c index 5006970..08652b2 100644 --- a/src/dungeon_ai_item_weight.c +++ b/src/dungeon_ai_item_weight.c @@ -448,7 +448,7 @@ bool8 CanTargetAdjacentPokemon(struct DungeonEntity *pokemon) s32 facingDir; for (facingDir = 0; facingDir < NUM_DIRECTIONS; facingDir++) { - struct MapTile *mapTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[facingDir].x, pokemon->posWorld.y + gAdjacentTileOffsets[facingDir].y); + struct MapTile *mapTile = GetMapTile_1(pokemon->posWorld.x + gAdjacentTileOffsets[facingDir].x, pokemon->posWorld.y + gAdjacentTileOffsets[facingDir].y); struct DungeonEntity *adjacentPokemon = mapTile->pokemon; if (adjacentPokemon != NULL && GetEntityType(adjacentPokemon) != ENTITY_NONE && CanTarget(pokemon, adjacentPokemon, FALSE, TRUE) == TARGET_CAPABILITY_CAN_TARGET) diff --git a/src/dungeon_ai_items.c b/src/dungeon_ai_items.c index 183d143..52aacc4 100644 --- a/src/dungeon_ai_items.c +++ b/src/dungeon_ai_items.c @@ -158,7 +158,7 @@ void DecideUseItem(struct DungeonEntity *pokemon) else if (toolboxIndex == 0) { // This seems unused. toolboxIndex can never be 0. - struct MapTile *mapTile = GetMapTileAtPosition(pokemon->posWorld.x, pokemon->posWorld.y); + struct MapTile *mapTile = GetMapTile_1(pokemon->posWorld.x, pokemon->posWorld.y); struct DungeonEntity *mapObject = mapTile->mapObject; if (mapObject != null) { diff --git a/src/dungeon_ai_movement.c b/src/dungeon_ai_movement.c index 5fa6d87..49609d7 100644 --- a/src/dungeon_ai_movement.c +++ b/src/dungeon_ai_movement.c @@ -49,7 +49,7 @@ u32 sub_8075818(struct DungeonEntity *entity) entityData = entity->entityData; if(EntityExists(entity)) { - tile = GetMapEntityForDungeonEntity(entity); + tile = GetMapTileForDungeonEntity_2(entity); if(HasIQSkill(entity, IQ_SKILL_SUPER_MOBILE)) if(!(tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) return 1; @@ -136,7 +136,7 @@ void sub_8075900(struct DungeonEntity *pokemon, u8 r1) { if(!gDungeonGlobalData->monsterHouseActive) { - if((GetMapEntityForDungeonEntity(pokemon)->tileType & TILE_TYPE_MONSTER_HOUSE)) + if((GetMapTileForDungeonEntity_2(pokemon)->tileType & TILE_TYPE_MONSTER_HOUSE)) { // It's a monster house! SendMessage(GetLeaderEntity(), gPtrItsaMonsterHouseMessage); diff --git a/src/dungeon_capabilities_1.c b/src/dungeon_capabilities_1.c index e6ec6fa..605f9e9 100644 --- a/src/dungeon_capabilities_1.c +++ b/src/dungeon_capabilities_1.c @@ -89,7 +89,7 @@ bool8 CannotAttack(struct DungeonEntity *pokemon, bool8 skipSleep) bool8 CanMoveInDirection(struct DungeonEntity *pokemon, u32 facingDir) { u8 crossableTerrain = GetCrossableTerrain(pokemon->entityData->entityID); - struct MapTile *currentMapTile = GetMapTileAtPosition(pokemon->posWorld.x + gAdjacentTileOffsets[facingDir].x, + struct MapTile *currentMapTile = GetMapTile_1(pokemon->posWorld.x + gAdjacentTileOffsets[facingDir].x, pokemon->posWorld.y + gAdjacentTileOffsets[facingDir].y); if (currentMapTile->tileType & TILE_TYPE_MAP_EDGE || currentMapTile->pokemon != NULL) { @@ -118,7 +118,7 @@ bool8 CanMoveInDirection(struct DungeonEntity *pokemon, u32 facingDir) } } } - currentMapTile = GetMapTileAtPosition(pokemon->posWorld.x, pokemon->posWorld.y); + currentMapTile = GetMapTile_1(pokemon->posWorld.x, pokemon->posWorld.y); if (!(currentMapTile->canMoveAdjacent[crossableTerrain] & gDirectionBitMasks[facingDir & DIRECTION_MASK])) { return FALSE; diff --git a/src/dungeon_map_access.c b/src/dungeon_map_access.c index 43e0e4d..9ffa633 100644 --- a/src/dungeon_map_access.c +++ b/src/dungeon_map_access.c @@ -3,13 +3,25 @@ #include "dungeon_global_data.h" -extern struct MapTile *gUnknown_203B430; +extern struct unkStruct_202F190 gUnknown_202F190; +extern struct unkStruct_202F190 *gUnknown_203B430; -struct MapTile* GetMapTileAtPosition(s32 x, s32 y) +struct MapTile* GetMapTile_1(s32 x, s32 y) { if (x >= 0 && y >= 0 && x < DUNGEON_MAX_SIZE_X && y < DUNGEON_MAX_SIZE_Y) { - return gDungeonGlobalData->mapEntityPointers[y][x]; + return gDungeonGlobalData->mapTilePointers[y][x]; } - return gUnknown_203B430; + return (struct MapTile*) gUnknown_203B430->unk0; +} + +struct MapTile* GetMapTile_2(s32 x, s32 y) +{ + if (x < 0 || y < 0 || x >= DUNGEON_MAX_SIZE_X || y >= DUNGEON_MAX_SIZE_Y) + { + struct MapTile* tile = (struct MapTile*) gUnknown_202F190.unk0; + gUnknown_202F190 = *gUnknown_203B430; + return tile; + } + return gDungeonGlobalData->mapTilePointers[y][x]; } diff --git a/src/dungeon_range.c b/src/dungeon_range.c index facd71d..00b827d 100644 --- a/src/dungeon_range.c +++ b/src/dungeon_range.c @@ -14,7 +14,7 @@ bool8 InSameRoom_2(struct Position *pos1, struct Position *pos2) { visibility = 2; } - tile1 = GetMapTileAtPosition(pos1->x, pos1->y); + tile1 = GetMapTile_1(pos1->x, pos1->y); pos1RoomIndex = tile1->roomIndex; if (pos1RoomIndex == CORRIDOR_ROOM_INDEX) { diff --git a/src/dungeon_util.c b/src/dungeon_util.c index c5b5695..1d443c0 100644 --- a/src/dungeon_util.c +++ b/src/dungeon_util.c @@ -14,8 +14,6 @@ const struct Position gAdjacentTileOffsets[] = { {-1, 1} }; -extern struct MapTile* GetMapEntity(s16, s16); - bool8 EntityExists(struct DungeonEntity *entity) { if (!entity) @@ -55,12 +53,12 @@ struct DungeonEntityData* sub_8045110(struct DungeonEntity *entity) return entity->entityData; } -struct MapTile* GetMapTileForDungeonEntity(struct DungeonEntity *entity) +struct MapTile* GetMapTileForDungeonEntity_1(struct DungeonEntity *entity) { - return GetMapTileAtPosition(entity->posWorld.x, entity->posWorld.y); + return GetMapTile_1(entity->posWorld.x, entity->posWorld.y); } -struct MapTile* GetMapEntityForDungeonEntity(struct DungeonEntity *entity) +struct MapTile* GetMapTileForDungeonEntity_2(struct DungeonEntity *entity) { - return GetMapEntity(entity->posWorld.x, entity->posWorld.y); + return GetMapTile_2(entity->posWorld.x, entity->posWorld.y); } diff --git a/src/status_checker.c b/src/status_checker.c index 379082f..7fbfc51 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -348,14 +348,14 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_DIVE: - if (IsTileGround(GetMapEntityForDungeonEntity(pokemon))) + if (IsTileGround(GetMapTileForDungeonEntity_2(pokemon))) { return FALSE; } break; case MOVE_DIG: { - struct MapTile *tile = GetMapEntityForDungeonEntity(pokemon); + struct MapTile *tile = GetMapTileForDungeonEntity_2(pokemon); if (!IsTileGround(tile) || (tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)) != TILE_TYPE_FLOOR) { return FALSE; @@ -364,7 +364,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } case MOVE_TRAP_BUSTER: { - struct DungeonEntity *mapObject = GetMapEntityForDungeonEntity(pokemon)->mapObject; + struct DungeonEntity *mapObject = GetMapTileForDungeonEntity_2(pokemon)->mapObject; if (mapObject == NULL || GetEntityType(mapObject) != ENTITY_TRAP) { return FALSE; -- cgit v1.2.3 From e54b3427db443f40cc07da650f64c1573ae0d4a0 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 22:12:40 -0500 Subject: Decomped IsBossBattle() --- src/dungeon_engine.c | 11 ++++++++++- src/status_checker.c | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dungeon_engine.c b/src/dungeon_engine.c index dd25441..20c3a50 100644 --- a/src/dungeon_engine.c +++ b/src/dungeon_engine.c @@ -3,6 +3,15 @@ #include "constants/dungeon.h" #include "dungeon_global_data.h" +bool8 IsBossBattle() +{ + if (gDungeonGlobalData->bossBattleIndex != 0 && gDungeonGlobalData->bossBattleIndex <= 0x31) + { + return TRUE; + } + return FALSE; +} + bool8 IsFixedDungeon() { if (gDungeonGlobalData->tileset > DUNGEON_OUT_ON_RESCUE) @@ -10,4 +19,4 @@ bool8 IsFixedDungeon() return TRUE; } return FALSE; -} +} \ No newline at end of file diff --git a/src/status_checker.c b/src/status_checker.c index 7fbfc51..612e6cd 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -5,6 +5,7 @@ #include "constants/status.h" #include "constants/type.h" #include "constants/weather.h" +#include "dungeon_engine.h" #include "dungeon_global_data.h" #include "dungeon_pokemon_attributes.h" #include "dungeon_util.h" @@ -93,7 +94,6 @@ const u8 gDungeonCamouflageTypes[76] = { TYPE_ROCK }; -extern bool8 IsBossBattle(); extern u8 GetWeather(struct DungeonEntity*); extern bool8 HasQuarterHPOrLess(struct DungeonEntity*); extern bool8 IsTileGround(struct MapTile*); -- cgit v1.2.3 From 7c714bd14e68ee9528512108e8b2cbd7f9da46c7 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 22:30:05 -0500 Subject: Decomped GetWeather() --- src/status_checker.c | 2 +- src/weather.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/weather.c (limited to 'src') diff --git a/src/status_checker.c b/src/status_checker.c index 612e6cd..6f521f1 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -13,6 +13,7 @@ #include "map.h" #include "number_util.h" #include "status_checks_1.h" +#include "weather.h" // Array indices correspond to the current dungeon tileset. const u8 gDungeonCamouflageTypes[76] = { @@ -94,7 +95,6 @@ const u8 gDungeonCamouflageTypes[76] = { TYPE_ROCK }; -extern u8 GetWeather(struct DungeonEntity*); extern bool8 HasQuarterHPOrLess(struct DungeonEntity*); extern bool8 IsTileGround(struct MapTile*); extern bool8 CanLayTrap(struct Position*); diff --git a/src/weather.c b/src/weather.c new file mode 100644 index 0000000..3989790 --- /dev/null +++ b/src/weather.c @@ -0,0 +1,16 @@ +#include "global.h" +#include "weather.h" + +#include "constants/item.h" +#include "constants/weather.h" +#include "dungeon_global_data.h" +#include "dungeon_items.h" + +u8 GetWeather(struct DungeonEntity* pokemon) +{ + if (pokemon != NULL && HasItem(pokemon, ITEM_ID_WEATHER_BAND)) + { + return WEATHER_CLEAR; + } + return gDungeonGlobalData->weather; +} -- cgit v1.2.3 From ec6abc684ebc571fc186ca61f1410770ea17fa14 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 22:51:36 -0500 Subject: Decomped HasQuarterHPOrLess --- src/status_checker.c | 1 - src/status_checks_1.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/status_checker.c b/src/status_checker.c index 6f521f1..e0bf251 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -95,7 +95,6 @@ const u8 gDungeonCamouflageTypes[76] = { TYPE_ROCK }; -extern bool8 HasQuarterHPOrLess(struct DungeonEntity*); extern bool8 IsTileGround(struct MapTile*); extern bool8 CanLayTrap(struct Position*); diff --git a/src/status_checks_1.c b/src/status_checks_1.c index 9d0bfe8..c49e127 100644 --- a/src/status_checks_1.c +++ b/src/status_checks_1.c @@ -53,3 +53,19 @@ bool8 IsSleeping(struct DungeonEntity *pokemon) } return TRUE; } + +bool8 HasQuarterHPOrLess(struct DungeonEntity* pokemon) +{ + struct DungeonEntityData *pokemonData = pokemon->entityData; + struct DungeonEntityData *pokemonData2 = pokemon->entityData; + s32 maxHP = pokemonData->maxHP; + if (maxHP < 0) + { + maxHP += 3; + } + if (pokemonData2->HP <= maxHP >> 2) + { + return TRUE; + } + return FALSE; +} -- cgit v1.2.3 From 4aafa434a61c07b70e6bc2364ab6f63c7e2c4169 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 23:43:06 -0500 Subject: Decomped IsTileGround() --- src/status_checker.c | 2 +- src/tile_types.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/tile_types.c (limited to 'src') diff --git a/src/status_checker.c b/src/status_checker.c index e0bf251..667f0cb 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -13,6 +13,7 @@ #include "map.h" #include "number_util.h" #include "status_checks_1.h" +#include "tile_types.h" #include "weather.h" // Array indices correspond to the current dungeon tileset. @@ -95,7 +96,6 @@ const u8 gDungeonCamouflageTypes[76] = { TYPE_ROCK }; -extern bool8 IsTileGround(struct MapTile*); extern bool8 CanLayTrap(struct Position*); bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move) diff --git a/src/tile_types.c b/src/tile_types.c new file mode 100644 index 0000000..fe28d9d --- /dev/null +++ b/src/tile_types.c @@ -0,0 +1,103 @@ +#include "global.h" +#include "tile_types.h" + +#include "dungeon_global_data.h" + +const u8 gDungeonWaterType[] = { + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_WATER, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_WATER, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_LAVA, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_LAVA, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_LAVA, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_LAVA, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, + DUNGEON_WATER_TYPE_NONE, +}; + +extern bool8 IsWaterTileset(); + +bool8 IsTileGround(struct MapTile* tile) +{ + bool8 isGround = FALSE; + if (IsWaterTileset()) + { + if (!(tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) + { + isGround = TRUE; + } + } + else if ((tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)) != TILE_TYPE_LIQUID || + gDungeonWaterType[gDungeonGlobalData->tileset] == DUNGEON_WATER_TYPE_LAVA) + { + isGround = TRUE; + } + return isGround; +} -- cgit v1.2.3 From 07795b6ff619c30426ad279ef840842ef3dea2ac Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sun, 20 Feb 2022 23:59:57 -0500 Subject: Decomped IsWaterTileset() --- src/tile_types.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tile_types.c b/src/tile_types.c index fe28d9d..cad63fa 100644 --- a/src/tile_types.c +++ b/src/tile_types.c @@ -82,8 +82,6 @@ const u8 gDungeonWaterType[] = { DUNGEON_WATER_TYPE_NONE, }; -extern bool8 IsWaterTileset(); - bool8 IsTileGround(struct MapTile* tile) { bool8 isGround = FALSE; @@ -101,3 +99,16 @@ bool8 IsTileGround(struct MapTile* tile) } return isGround; } + +bool8 IsWaterTileset() +{ + if (gDungeonGlobalData->tileset == 0 || + gDungeonGlobalData->tileset == 0x31 || + gDungeonGlobalData->tileset == 0x20 || + gDungeonGlobalData->tileset == 0x21 || + gDungeonGlobalData->tileset == 0x36) + { + return TRUE; + } + return FALSE; +} -- cgit v1.2.3 From 33d2d6175067e75cd222b8f05234221ec2d2b82b Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Mon, 21 Feb 2022 15:40:12 -0500 Subject: Decomped CanLayTrap() --- src/status_checker.c | 3 +-- src/trap.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/trap.c (limited to 'src') diff --git a/src/status_checker.c b/src/status_checker.c index 667f0cb..07d6c7f 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -14,6 +14,7 @@ #include "number_util.h" #include "status_checks_1.h" #include "tile_types.h" +#include "trap.h" #include "weather.h" // Array indices correspond to the current dungeon tileset. @@ -96,8 +97,6 @@ const u8 gDungeonCamouflageTypes[76] = { TYPE_ROCK }; -extern bool8 CanLayTrap(struct Position*); - bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move) { struct DungeonEntityData *pokemonData = pokemon->entityData; diff --git a/src/trap.c b/src/trap.c new file mode 100644 index 0000000..e054706 --- /dev/null +++ b/src/trap.c @@ -0,0 +1,27 @@ +#include "global.h" +#include "trap.h" + +#include "dungeon_map_access.h" +#include "dungeon_util.h" +#include "map.h" + +bool8 CanLayTrap(struct Position *pos) +{ + struct MapTile *tile = GetMapTile_2(pos->x, pos->y); + if (tile->tileType & TILE_TYPE_STAIRS || + tile->roomIndex == CORRIDOR_ROOM_INDEX || + tile->tileType & TILE_TYPE_ROOM_EXIT) + { + return FALSE; + } + if (tile->tileType & TILE_TYPE_SHOP) + { + return FALSE; + } + if ((tile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID)) != TILE_TYPE_FLOOR || + (tile->mapObject != NULL && GetEntityType(tile->mapObject) != ENTITY_TRAP)) + { + return FALSE; + } + return TRUE; +} -- cgit v1.2.3 From 598a588589cb581b269f2e46373c657ec897a3a3 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Mon, 21 Feb 2022 15:59:34 -0500 Subject: Decomped CanAttackInFront() --- src/dungeon_ai.c | 62 ------------------------- src/dungeon_ai_1.c | 105 ------------------------------------------- src/dungeon_ai_attack.c | 8 ++-- src/dungeon_ai_item_weight.c | 2 +- src/dungeon_ai_items.c | 2 +- src/dungeon_ai_targeting.c | 62 +++++++++++++++++++++++++ src/dungeon_ai_targeting_1.c | 62 +++++++++++++++++++++++++ src/dungeon_ai_targeting_2.c | 105 +++++++++++++++++++++++++++++++++++++++++++ src/dungeon_capabilities_1.c | 6 +-- 9 files changed, 238 insertions(+), 176 deletions(-) delete mode 100644 src/dungeon_ai.c delete mode 100644 src/dungeon_ai_1.c create mode 100644 src/dungeon_ai_targeting.c create mode 100644 src/dungeon_ai_targeting_1.c create mode 100644 src/dungeon_ai_targeting_2.c (limited to 'src') diff --git a/src/dungeon_ai.c b/src/dungeon_ai.c deleted file mode 100644 index b2e3b2e..0000000 --- a/src/dungeon_ai.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "global.h" -#include "dungeon_ai.h" - -#include "constants/ability.h" -#include "constants/tactic.h" -#include "dungeon_pokemon_attributes.h" -#include "dungeon_util.h" - -extern void CheckRunAwayVisualFlag(struct DungeonEntity *, bool8 showRunAwayEffect); - -bool8 ShouldAvoidFirstHit(struct DungeonEntity *pokemon, bool8 forceAvoid) -{ - if (!HasTactic(pokemon, TACTIC_AVOID_THE_FIRST_HIT)) - return FALSE; - if (!forceAvoid) - return FALSE; - return TRUE; -} - -bool8 ShouldAvoidEnemies(struct DungeonEntity *pokemon) -{ - if (!EntityExists(pokemon)) - { - return FALSE; - } - else - { - struct DungeonEntityData *pokemonData = pokemon->entityData; - if (pokemonData->terrifiedTurnsLeft != 0) - { - return TRUE; - } - if (pokemonData->isLeader) - { - return FALSE; - } - if (HasAbility(pokemon, ABILITY_RUN_AWAY)) - { - bool8 runAwayActive = pokemonData->HP < pokemonData->maxHP / 2; - if (runAwayActive) - { - return TRUE; - } - } - if (HasTactic(pokemon, TACTIC_GET_AWAY) || - (HasTactic(pokemon, TACTIC_AVOID_TROUBLE) && pokemonData->HP <= pokemonData->maxHP / 2)) - { - return TRUE; - } - return FALSE; - } -} - -bool8 ShouldAvoidEnemiesAndShowEffect(struct DungeonEntity *pokemon, bool8 showRunAwayEffect) -{ - if (ShouldAvoidEnemies(pokemon)) - { - CheckRunAwayVisualFlag(pokemon, showRunAwayEffect); - return TRUE; - } - return FALSE; -} diff --git a/src/dungeon_ai_1.c b/src/dungeon_ai_1.c deleted file mode 100644 index 78c899f..0000000 --- a/src/dungeon_ai_1.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "global.h" -#include "dungeon_ai_1.h" - -#include "constants/status.h" -#include "constants/targeting.h" -#include "dungeon_pokemon_attributes.h" - -const u8 gTargetingData[3][2][2][2] = { - { - { - {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, - {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} - }, - { - {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, - {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} - } - }, - { - { - {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, - {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} - }, - { - {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET}, - {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET} - } - }, - { - { - {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET}, - {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET} - }, - { - {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, - {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} - } - } -}; - -u8 CanTarget(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, bool8 ignoreInvisible, bool8 checkPetrified) -{ - struct DungeonEntityData *pokemonData = pokemon->entityData; - struct DungeonEntityData *targetData = targetPokemon->entityData; - u8 targetingDecoy; - u8 pokemonTargetingDecoy; - bool8 pokemonIsEnemy; - bool8 targetIsEnemy; - bool8 targetIsDecoy; - if (pokemon == targetPokemon) - { - return TARGET_CAPABILITY_CANNOT_ATTACK; - } - if (pokemonData->shopkeeperMode == SHOPKEEPER_FRIENDLY || - targetData->shopkeeperMode == SHOPKEEPER_FRIENDLY || - pokemonData->clientType == CLIENT_TYPE_DONT_MOVE || - targetData->clientType == CLIENT_TYPE_DONT_MOVE || - pokemonData->clientType == CLIENT_TYPE_CLIENT || - targetData->clientType == CLIENT_TYPE_CLIENT || - (checkPetrified && !pokemonData->isEnemy && targetData->immobilizeStatus == IMMOBILIZE_STATUS_PETRIFIED) || - (!ignoreInvisible && targetData->transformStatus == TRANSFORM_STATUS_INVISIBLE && !CanSeeInvisible(pokemon))) - { - return TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET; - } - pokemonTargetingDecoy = pokemonData->targetingDecoy; - targetingDecoy = TARGETING_DECOY_NONE; - if (pokemonTargetingDecoy != TARGETING_DECOY_NONE) - { - targetingDecoy = TARGETING_DECOY_WILD; - if (pokemonTargetingDecoy == TARGETING_DECOY_TEAM) - { - targetingDecoy = TARGETING_DECOY_TEAM; - } - } - if (pokemonData->shopkeeperMode != SHOPKEEPER_NONE) - { - pokemonIsEnemy = FALSE; - if (pokemonData->shopkeeperMode == SHOPKEEPER_AGGRESSIVE_TO_PLAYER) - { - pokemonIsEnemy = TRUE; - } - } - else - { - pokemonIsEnemy = pokemonData->isEnemy ? TRUE : FALSE; - } - if (targetData->shopkeeperMode != SHOPKEEPER_NONE) - { - targetIsEnemy = FALSE; - if (targetData->shopkeeperMode == SHOPKEEPER_AGGRESSIVE_TO_PLAYER) - { - targetIsEnemy = TRUE; - } - } - else - { - targetIsEnemy = targetData->isEnemy ? TRUE : FALSE; - } - targetIsDecoy = FALSE; - if (targetData->waitingStatus == WAITING_STATUS_DECOY) - { - targetIsDecoy = TRUE; - } - return gTargetingData[targetingDecoy][pokemonIsEnemy][targetIsEnemy][targetIsDecoy]; -} diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 092bab5..7368e66 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -10,7 +10,8 @@ #include "constants/type.h" #include "charge_move.h" #include "dungeon_action.h" -#include "dungeon_ai.h" +#include "dungeon_ai_targeting.h" +#include "dungeon_ai_targeting_1.h" #include "dungeon_ai_attack_1.h" #include "dungeon_capabilities_1.h" #include "dungeon_global_data.h" @@ -37,9 +38,8 @@ extern s32 gPotentialTargetWeights_2[NUM_DIRECTIONS]; extern u8 gPotentialAttackTargetDirections[NUM_DIRECTIONS]; extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS]; -extern bool8 IsMoveUsable(struct DungeonEntity*, s32, bool8); +extern bool8 IsMoveUsable_1(struct DungeonEntity*, s32, bool8); extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8); -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); extern bool8 CanUseStatusMove(s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, bool8); @@ -182,7 +182,7 @@ void DecideAttack(struct DungeonEntity *pokemon) move = &pokemonData->moves[i]; if (move->moveFlags & MOVE_FLAG_EXISTS && willNotUnlinkMove[i] && - IsMoveUsable(pokemon, i, hasPPChecker) && + IsMoveUsable_1(pokemon, i, hasPPChecker) && move->moveFlags & MOVE_FLAG_ENABLED) { moveTargetResults[i].moveUsable = TRUE; diff --git a/src/dungeon_ai_item_weight.c b/src/dungeon_ai_item_weight.c index 08652b2..ce79ad4 100644 --- a/src/dungeon_ai_item_weight.c +++ b/src/dungeon_ai_item_weight.c @@ -3,7 +3,7 @@ #include "constants/status.h" #include "constants/targeting.h" -#include "dungeon_ai_1.h" +#include "dungeon_ai_targeting_2.h" #include "dungeon_map_access.h" #include "dungeon_pokemon_attributes.h" #include "dungeon_util.h" diff --git a/src/dungeon_ai_items.c b/src/dungeon_ai_items.c index 52aacc4..0135c62 100644 --- a/src/dungeon_ai_items.c +++ b/src/dungeon_ai_items.c @@ -6,10 +6,10 @@ #include "constants/status.h" #include "constants/targeting.h" #include "dungeon_action.h" -#include "dungeon_ai_1.h" #include "dungeon_ai_attack_1.h" #include "dungeon_ai_item_weight.h" #include "dungeon_ai_items.h" +#include "dungeon_ai_targeting_2.h" #include "dungeon_capabilities.h" #include "dungeon_capabilities_1.h" #include "dungeon_entity.h" diff --git a/src/dungeon_ai_targeting.c b/src/dungeon_ai_targeting.c new file mode 100644 index 0000000..ec5abd9 --- /dev/null +++ b/src/dungeon_ai_targeting.c @@ -0,0 +1,62 @@ +#include "global.h" +#include "dungeon_ai_targeting.h" + +#include "constants/iq_skill.h" +#include "constants/item.h" +#include "constants/status.h" +#include "dungeon_engine.h" +#include "dungeon_items.h" +#include "dungeon_map_access.h" +#include "dungeon_movement.h" +#include "dungeon_pokemon_attributes.h" +#include "dungeon_util.h" +#include "map.h" + +const u8 gDirectionBitMasks_2[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; + +bool8 CanAttackInFront(struct DungeonEntity *pokemon, s32 direction) +{ + u8 crossableTerrain = GetCrossableTerrain(pokemon->entityData->entityID); + struct MapTile *tile; + if (crossableTerrain < CROSSABLE_TERRAIN_CREVICE) + { + crossableTerrain = CROSSABLE_TERRAIN_CREVICE; + } + tile = GetMapTile_1(pokemon->posWorld.x + gAdjacentTileOffsets[direction].x, + pokemon->posWorld.y + gAdjacentTileOffsets[direction].y); + if (!(tile->tileType & TILE_TYPE_MAP_EDGE) && + (tile->pokemon == NULL || GetEntityType(tile->pokemon) == ENTITY_POKEMON)) + { + if (!IsFixedDungeon()) + { + if (pokemon->entityData->transformStatus == TRANSFORM_STATUS_MOBILE || + HasItem(pokemon, ITEM_ID_MOBILE_SCARF)) + { + crossableTerrain = CROSSABLE_TERRAIN_WALL; + } + else if (HasIQSkill(pokemon, IQ_SKILL_ALL_TERRAIN_HIKER)) + { + // BUG: If the Pokémon is a Ghost type that can normally attack through walls, + // All-Terrain Hiker/Super Mobile may make the AI think it can't attack through walls. + crossableTerrain = CROSSABLE_TERRAIN_CREVICE; + } + else if (HasIQSkill(pokemon, IQ_SKILL_SUPER_MOBILE)) + { + if ((direction & 1) != 0) + { + crossableTerrain = CROSSABLE_TERRAIN_CREVICE; + } + else + { + crossableTerrain = CROSSABLE_TERRAIN_WALL; + } + } + } + tile = GetMapTile_1(pokemon->posWorld.x, pokemon->posWorld.y); + if (tile->canMoveAdjacent[crossableTerrain] & gDirectionBitMasks_2[direction & DIRECTION_MASK]) + { + return TRUE; + } + } + return FALSE; +} diff --git a/src/dungeon_ai_targeting_1.c b/src/dungeon_ai_targeting_1.c new file mode 100644 index 0000000..5ff76b0 --- /dev/null +++ b/src/dungeon_ai_targeting_1.c @@ -0,0 +1,62 @@ +#include "global.h" +#include "dungeon_ai_targeting_1.h" + +#include "constants/ability.h" +#include "constants/tactic.h" +#include "dungeon_pokemon_attributes.h" +#include "dungeon_util.h" + +extern void CheckRunAwayVisualFlag(struct DungeonEntity *, bool8 showRunAwayEffect); + +bool8 ShouldAvoidFirstHit(struct DungeonEntity *pokemon, bool8 forceAvoid) +{ + if (!HasTactic(pokemon, TACTIC_AVOID_THE_FIRST_HIT)) + return FALSE; + if (!forceAvoid) + return FALSE; + return TRUE; +} + +bool8 ShouldAvoidEnemies(struct DungeonEntity *pokemon) +{ + if (!EntityExists(pokemon)) + { + return FALSE; + } + else + { + struct DungeonEntityData *pokemonData = pokemon->entityData; + if (pokemonData->terrifiedTurnsLeft != 0) + { + return TRUE; + } + if (pokemonData->isLeader) + { + return FALSE; + } + if (HasAbility(pokemon, ABILITY_RUN_AWAY)) + { + bool8 runAwayActive = pokemonData->HP < pokemonData->maxHP / 2; + if (runAwayActive) + { + return TRUE; + } + } + if (HasTactic(pokemon, TACTIC_GET_AWAY) || + (HasTactic(pokemon, TACTIC_AVOID_TROUBLE) && pokemonData->HP <= pokemonData->maxHP / 2)) + { + return TRUE; + } + return FALSE; + } +} + +bool8 ShouldAvoidEnemiesAndShowEffect(struct DungeonEntity *pokemon, bool8 showRunAwayEffect) +{ + if (ShouldAvoidEnemies(pokemon)) + { + CheckRunAwayVisualFlag(pokemon, showRunAwayEffect); + return TRUE; + } + return FALSE; +} diff --git a/src/dungeon_ai_targeting_2.c b/src/dungeon_ai_targeting_2.c new file mode 100644 index 0000000..83319e1 --- /dev/null +++ b/src/dungeon_ai_targeting_2.c @@ -0,0 +1,105 @@ +#include "global.h" +#include "dungeon_ai_targeting_2.h" + +#include "constants/status.h" +#include "constants/targeting.h" +#include "dungeon_pokemon_attributes.h" + +const u8 gTargetingData[3][2][2][2] = { + { + { + {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, + {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} + }, + { + {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, + {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} + } + }, + { + { + {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, + {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} + }, + { + {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET}, + {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET} + } + }, + { + { + {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET}, + {TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET, TARGET_CAPABILITY_CAN_TARGET} + }, + { + {TARGET_CAPABILITY_CAN_TARGET, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET}, + {TARGET_CAPABILITY_CANNOT_ATTACK, TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET} + } + } +}; + +u8 CanTarget(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, bool8 ignoreInvisible, bool8 checkPetrified) +{ + struct DungeonEntityData *pokemonData = pokemon->entityData; + struct DungeonEntityData *targetData = targetPokemon->entityData; + u8 targetingDecoy; + u8 pokemonTargetingDecoy; + bool8 pokemonIsEnemy; + bool8 targetIsEnemy; + bool8 targetIsDecoy; + if (pokemon == targetPokemon) + { + return TARGET_CAPABILITY_CANNOT_ATTACK; + } + if (pokemonData->shopkeeperMode == SHOPKEEPER_FRIENDLY || + targetData->shopkeeperMode == SHOPKEEPER_FRIENDLY || + pokemonData->clientType == CLIENT_TYPE_DONT_MOVE || + targetData->clientType == CLIENT_TYPE_DONT_MOVE || + pokemonData->clientType == CLIENT_TYPE_CLIENT || + targetData->clientType == CLIENT_TYPE_CLIENT || + (checkPetrified && !pokemonData->isEnemy && targetData->immobilizeStatus == IMMOBILIZE_STATUS_PETRIFIED) || + (!ignoreInvisible && targetData->transformStatus == TRANSFORM_STATUS_INVISIBLE && !CanSeeInvisible(pokemon))) + { + return TARGET_CAPABILITY_CAN_ATTACK_NOT_TARGET; + } + pokemonTargetingDecoy = pokemonData->targetingDecoy; + targetingDecoy = TARGETING_DECOY_NONE; + if (pokemonTargetingDecoy != TARGETING_DECOY_NONE) + { + targetingDecoy = TARGETING_DECOY_WILD; + if (pokemonTargetingDecoy == TARGETING_DECOY_TEAM) + { + targetingDecoy = TARGETING_DECOY_TEAM; + } + } + if (pokemonData->shopkeeperMode != SHOPKEEPER_NONE) + { + pokemonIsEnemy = FALSE; + if (pokemonData->shopkeeperMode == SHOPKEEPER_AGGRESSIVE_TO_PLAYER) + { + pokemonIsEnemy = TRUE; + } + } + else + { + pokemonIsEnemy = pokemonData->isEnemy ? TRUE : FALSE; + } + if (targetData->shopkeeperMode != SHOPKEEPER_NONE) + { + targetIsEnemy = FALSE; + if (targetData->shopkeeperMode == SHOPKEEPER_AGGRESSIVE_TO_PLAYER) + { + targetIsEnemy = TRUE; + } + } + else + { + targetIsEnemy = targetData->isEnemy ? TRUE : FALSE; + } + targetIsDecoy = FALSE; + if (targetData->waitingStatus == WAITING_STATUS_DECOY) + { + targetIsDecoy = TRUE; + } + return gTargetingData[targetingDecoy][pokemonIsEnemy][targetIsEnemy][targetIsDecoy]; +} diff --git a/src/dungeon_capabilities_1.c b/src/dungeon_capabilities_1.c index 605f9e9..ef566fe 100644 --- a/src/dungeon_capabilities_1.c +++ b/src/dungeon_capabilities_1.c @@ -5,7 +5,7 @@ #include "constants/iq_skill.h" #include "constants/status.h" #include "charge_move.h" -#include "dungeon_ai.h" +#include "dungeon_ai_targeting_1.h" #include "dungeon_capabilities.h" #include "dungeon_engine.h" #include "dungeon_items.h" @@ -15,7 +15,7 @@ #include "dungeon_util.h" #include "map.h" -const u8 gDirectionBitMasks[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; +const u8 gDirectionBitMasks_1[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; static inline bool8 JoinLocationCannotUseItems(struct DungeonEntityData *pokemonData) { @@ -119,7 +119,7 @@ bool8 CanMoveInDirection(struct DungeonEntity *pokemon, u32 facingDir) } } currentMapTile = GetMapTile_1(pokemon->posWorld.x, pokemon->posWorld.y); - if (!(currentMapTile->canMoveAdjacent[crossableTerrain] & gDirectionBitMasks[facingDir & DIRECTION_MASK])) + if (!(currentMapTile->canMoveAdjacent[crossableTerrain] & gDirectionBitMasks_1[facingDir & DIRECTION_MASK])) { return FALSE; } -- cgit v1.2.3 From 40a34fafd685b7df6d1777ec335374ea081adad0 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Tue, 22 Feb 2022 22:38:57 -0500 Subject: Decomped WeightMoveIfUsable() --- src/dungeon_ai_attack.c | 20 ++--- src/dungeon_ai_attack_1.c | 194 +++++++++++++++++++++++++++++++--------------- src/dungeon_ai_attack_2.c | 76 ++++++++++++++++++ src/dungeon_ai_items.c | 10 +-- src/moves.c | 2 +- src/targeting_flags.c | 2 +- 6 files changed, 224 insertions(+), 80 deletions(-) create mode 100644 src/dungeon_ai_attack_2.c (limited to 'src') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 7368e66..65973a1 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -13,6 +13,7 @@ #include "dungeon_ai_targeting.h" #include "dungeon_ai_targeting_1.h" #include "dungeon_ai_attack_1.h" +#include "dungeon_ai_attack_2.h" #include "dungeon_capabilities_1.h" #include "dungeon_global_data.h" #include "dungeon_map_access.h" @@ -34,13 +35,12 @@ const s16 gRegularAttackWeights[] = {100, 20, 30, 40, 50}; extern bool8 gCanAttackInDirection[NUM_DIRECTIONS]; extern s32 gNumPotentialTargets; -extern s32 gPotentialTargetWeights_2[NUM_DIRECTIONS]; +extern s32 gPotentialAttackTargetWeights[NUM_DIRECTIONS]; extern u8 gPotentialAttackTargetDirections[NUM_DIRECTIONS]; extern struct DungeonEntity *gPotentialTargets[NUM_DIRECTIONS]; extern bool8 IsMoveUsable_1(struct DungeonEntity*, s32, bool8); extern bool8 TargetRegularAttack(struct DungeonEntity*, u32*, bool8); -extern s32 WeightMoveIfUsable(s32, s32, struct DungeonEntity*, struct DungeonEntity*, struct PokemonMove*, 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); @@ -366,7 +366,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn { gCanAttackInDirection[i] = TRUE; gPotentialAttackTargetDirections[numPotentialTargets] = i; - gPotentialTargetWeights_2[numPotentialTargets] = 99; + gPotentialAttackTargetWeights[numPotentialTargets] = 99; gPotentialTargets[numPotentialTargets] = NULL; numPotentialTargets++; } @@ -457,7 +457,7 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn { gCanAttackInDirection[facingDir] = TRUE; gPotentialAttackTargetDirections[numPotentialTargets] = facingDir; - gPotentialTargetWeights_2[numPotentialTargets] = WeightMove(pokemon, targetingFlags, target, GetMoveTypeForPokemon(pokemon, move)); + gPotentialAttackTargetWeights[numPotentialTargets] = WeightMove(pokemon, targetingFlags, target, GetMoveTypeForPokemon(pokemon, move)); gPotentialTargets[numPotentialTargets] = target; numPotentialTargets++; } @@ -492,27 +492,27 @@ s32 FindMoveTarget(struct MoveTargetResults *moveTargetResults, struct DungeonEn s32 i; for (i = 0; i < numPotentialTargets; i++) { - if (maxWeight < gPotentialTargetWeights_2[i]) + if (maxWeight < gPotentialAttackTargetWeights[i]) { - maxWeight = gPotentialTargetWeights_2[i]; + maxWeight = gPotentialAttackTargetWeights[i]; } } for (i = 0; i < numPotentialTargets; i++) { - if (maxWeight != gPotentialTargetWeights_2[i]) + if (maxWeight != gPotentialAttackTargetWeights[i]) { - gPotentialTargetWeights_2[i] = 0; + gPotentialAttackTargetWeights[i] = 0; } } moveWeight = maxWeight; for (i = 0; i < numPotentialTargets; i++) { - totalWeight += gPotentialTargetWeights_2[i]; + totalWeight += gPotentialAttackTargetWeights[i]; } weightCounter = DungeonRandomCapped(totalWeight); for (i = 0; i < numPotentialTargets; i++) { - weightCounter -= gPotentialTargetWeights_2[i]; + weightCounter -= gPotentialAttackTargetWeights[i]; if (weightCounter < 0) { break; diff --git a/src/dungeon_ai_attack_1.c b/src/dungeon_ai_attack_1.c index 641bc8c..fb088fb 100644 --- a/src/dungeon_ai_attack_1.c +++ b/src/dungeon_ai_attack_1.c @@ -1,76 +1,144 @@ #include "global.h" #include "dungeon_ai_attack_1.h" -#include "constants/iq_skill.h" -#include "dungeon_global_data.h" -#include "dungeon_map_access.h" +#include "constants/direction.h" #include "dungeon_pokemon_attributes.h" -#include "dungeon_util.h" +#include "position_util.h" -bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, s32 facingDir, s32 maxRange) +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); + +s32 WeightMoveIfUsable(s32 numPotentialTargets, s32 targetingFlags, struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move, bool32 hasStatusChecker) { - s32 posDiffX = pokemon->posWorld.x - targetPokemon->posWorld.x; - s32 effectiveMaxRange; - if (posDiffX < 0) - { - posDiffX = -posDiffX; - } - effectiveMaxRange = pokemon->posWorld.y - targetPokemon->posWorld.y; - if (effectiveMaxRange < 0) - { - effectiveMaxRange = -effectiveMaxRange; - } - if (effectiveMaxRange < posDiffX) + s32 facingDir; + s32 targetingFlags2 = (s16) targetingFlags; + bool8 hasStatusChecker2 = hasStatusChecker; + struct DungeonEntityData *userData = user->entityData; + if ((user->posWorld.x == target->posWorld.x && user->posWorld.y == target->posWorld.y) || + (targetingFlags2 & 0xF0) == TARGETING_FLAG_TARGET_ROOM || + (targetingFlags2 & 0xF0) == TARGETING_FLAG_TARGET_FLOOR || + (targetingFlags2 & 0xF0) == TARGETING_FLAG_TARGET_SELF) { - effectiveMaxRange = posDiffX; + facingDir = userData->action.facingDir; } - if (effectiveMaxRange > maxRange) + else { - effectiveMaxRange = maxRange; + facingDir = CalculateFacingDir(&user->posWorld, &target->posWorld); } - if (!HasIQSkill(pokemon, IQ_SKILL_COURSE_CHECKER)) + if (!gCanAttackInDirection[facingDir] && + CanUseStatusMove(targetingFlags2, user, target, move, hasStatusChecker2)) { - // BUG: effectiveMaxRange is already capped at maxRange, so this condition always evaluates to TRUE. - // The AI also has range checks elsewhere, so this doesn't become an issue in most cases. - // If the AI has the Long Toss or Pierce statuses and Course Checker is disabled, - // this incorrect check causes the AI to throw items at targets further than 10 tiles away. - if (effectiveMaxRange <= maxRange) - { - return TRUE; - } + gCanAttackInDirection[facingDir] = TRUE; + do { gPotentialAttackTargetDirections[numPotentialTargets] = facingDir; } while (0); + gPotentialAttackTargetWeights[numPotentialTargets] = WeightMove(user, targetingFlags2, target, GetMoveTypeForPokemon(user, move)); + gPotentialTargets[numPotentialTargets] = target; + numPotentialTargets++; } - else - { - s32 currentPosX = pokemon->posWorld.x; - s32 currentPosY = pokemon->posWorld.y; - s32 adjacentTileOffsetX = gAdjacentTileOffsets[facingDir].x; - s32 adjacentTileOffsetY = gAdjacentTileOffsets[facingDir].y; - s32 i; - for (i = 0; i <= effectiveMaxRange; i++) - { - struct MapTile *mapTile; - currentPosX += adjacentTileOffsetX; - currentPosY += adjacentTileOffsetY; - if (currentPosX <= 0 || currentPosY <= 0 || - currentPosX >= DUNGEON_MAX_SIZE_X - 1 || currentPosY >= DUNGEON_MAX_SIZE_Y - 1) - { - break; - } - while (0); // Extra label needed to swap branch locations in ASM. - mapTile = GetMapTile_1(currentPosX, currentPosY); - if (!(mapTile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) - { - break; - } - if (mapTile->pokemon == targetPokemon) - { - return TRUE; - } - if (mapTile->pokemon != NULL) - { - break; - } - } - } - return FALSE; + 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"); +// } diff --git a/src/dungeon_ai_attack_2.c b/src/dungeon_ai_attack_2.c new file mode 100644 index 0000000..41e924a --- /dev/null +++ b/src/dungeon_ai_attack_2.c @@ -0,0 +1,76 @@ +#include "global.h" +#include "dungeon_ai_attack_2.h" + +#include "constants/iq_skill.h" +#include "dungeon_global_data.h" +#include "dungeon_map_access.h" +#include "dungeon_pokemon_attributes.h" +#include "dungeon_util.h" + +bool8 IsTargetStraightAhead(struct DungeonEntity *pokemon, struct DungeonEntity *targetPokemon, s32 facingDir, s32 maxRange) +{ + s32 posDiffX = pokemon->posWorld.x - targetPokemon->posWorld.x; + s32 effectiveMaxRange; + if (posDiffX < 0) + { + posDiffX = -posDiffX; + } + effectiveMaxRange = pokemon->posWorld.y - targetPokemon->posWorld.y; + if (effectiveMaxRange < 0) + { + effectiveMaxRange = -effectiveMaxRange; + } + if (effectiveMaxRange < posDiffX) + { + effectiveMaxRange = posDiffX; + } + if (effectiveMaxRange > maxRange) + { + effectiveMaxRange = maxRange; + } + if (!HasIQSkill(pokemon, IQ_SKILL_COURSE_CHECKER)) + { + // BUG: effectiveMaxRange is already capped at maxRange, so this condition always evaluates to TRUE. + // The AI also has range checks elsewhere, so this doesn't become an issue in most cases. + // If the AI has the Long Toss or Pierce statuses and Course Checker is disabled, + // this incorrect check causes the AI to throw items at targets further than 10 tiles away. + if (effectiveMaxRange <= maxRange) + { + return TRUE; + } + } + else + { + s32 currentPosX = pokemon->posWorld.x; + s32 currentPosY = pokemon->posWorld.y; + s32 adjacentTileOffsetX = gAdjacentTileOffsets[facingDir].x; + s32 adjacentTileOffsetY = gAdjacentTileOffsets[facingDir].y; + s32 i; + for (i = 0; i <= effectiveMaxRange; i++) + { + struct MapTile *mapTile; + currentPosX += adjacentTileOffsetX; + currentPosY += adjacentTileOffsetY; + if (currentPosX <= 0 || currentPosY <= 0 || + currentPosX >= DUNGEON_MAX_SIZE_X - 1 || currentPosY >= DUNGEON_MAX_SIZE_Y - 1) + { + break; + } + while (0); // Extra label needed to swap branch locations in ASM. + mapTile = GetMapTile_1(currentPosX, currentPosY); + if (!(mapTile->tileType & (TILE_TYPE_FLOOR | TILE_TYPE_LIQUID))) + { + break; + } + if (mapTile->pokemon == targetPokemon) + { + return TRUE; + } + if (mapTile->pokemon != NULL) + { + break; + } + } + } + return FALSE; +} diff --git a/src/dungeon_ai_items.c b/src/dungeon_ai_items.c index 0135c62..31d57ff 100644 --- a/src/dungeon_ai_items.c +++ b/src/dungeon_ai_items.c @@ -6,7 +6,7 @@ #include "constants/status.h" #include "constants/targeting.h" #include "dungeon_action.h" -#include "dungeon_ai_attack_1.h" +#include "dungeon_ai_attack_2.h" #include "dungeon_ai_item_weight.h" #include "dungeon_ai_items.h" #include "dungeon_ai_targeting_2.h" @@ -39,7 +39,7 @@ enum ItemTargetFlag extern void sub_8077274(struct DungeonEntity *, struct DungeonEntity *); extern s32 gNumPotentialTargets; -extern u32 gPotentialTargetWeights[NUM_DIRECTIONS]; +extern u32 gPotentialItemTargetWeights[NUM_DIRECTIONS]; extern u32 gPotentialItemTargetDirections[NUM_DIRECTIONS]; extern bool8 gTargetAhead[NUM_DIRECTIONS]; extern struct TeamInventory *gTeamInventory_203B460; @@ -95,7 +95,7 @@ void DecideUseItem(struct DungeonEntity *pokemon) FindStraightThrowableTargets(pokemon, 2, item, 1); for (targetIndex = 0; targetIndex < gNumPotentialTargets; targetIndex++) { - if (RollPercentChance(gPotentialTargetWeights[targetIndex])) + if (RollPercentChance(gPotentialItemTargetWeights[targetIndex])) { SetAction(&pokemonData->action, DUNGEON_ACTION_THROW_ITEM_AI); pokemonData->action.actionUseIndex = selectedToolboxIndex; @@ -229,7 +229,7 @@ void DecideUseItem(struct DungeonEntity *pokemon) s32 thrownAIFlag; for (thrownAIFlag = ITEM_AI_FLAG_TARGET_ALLY; thrownAIFlag <= ITEM_AI_FLAG_TARGET_ENEMY; thrownAIFlag++) { - potentialTargetWeights = gPotentialTargetWeights; + potentialTargetWeights = gPotentialItemTargetWeights; if (GetItemAIFlag(item->itemIndex, thrownAIFlag)) { u8 itemType = GetItemType(item->itemIndex); @@ -422,7 +422,7 @@ void TargetThrownItem(struct DungeonEntity *pokemon, struct DungeonEntity *targe u32 *targetWeight; gTargetAhead[targetDirection] = TRUE; gPotentialItemTargetDirections[gNumPotentialTargets] = targetDirection; - targetWeight = &gPotentialTargetWeights[gNumPotentialTargets]; + targetWeight = &gPotentialItemTargetWeights[gNumPotentialTargets]; itemWeight = !ignoreRollChance ? EvaluateItem(targetPokemon, item, targetingFlags) : 100; *targetWeight = itemWeight; gNumPotentialTargets++; diff --git a/src/moves.c b/src/moves.c index 0874f00..a7caed6 100644 --- a/src/moves.c +++ b/src/moves.c @@ -158,7 +158,7 @@ void InitZeroedPPPokemonMove(struct PokemonMove *move, u16 moveID) move->PP = 0; } -s16 GetMoveTargetingFlags(struct PokemonMove *move, u32 isAI) +s16 GetMoveTargetingFlags(struct PokemonMove *move, bool32 isAI) { return gMovesData[move->moveID].targetingFlags[isAI]; } diff --git a/src/targeting_flags.c b/src/targeting_flags.c index f315cdf..bc6010b 100644 --- a/src/targeting_flags.c +++ b/src/targeting_flags.c @@ -6,7 +6,7 @@ #include "dungeon_pokemon_attributes.h" #include "moves.h" -s16 GetMoveTargetingFlagsForPokemon(struct DungeonEntity *pokemon, struct PokemonMove *move, u32 isAI) +s16 GetMoveTargetingFlagsForPokemon(struct DungeonEntity *pokemon, struct PokemonMove *move, bool32 isAI) { if (move->moveID == MOVE_CURSE && !isAI && !HasType(pokemon, TYPE_GHOST)) { -- cgit v1.2.3 From 6e56b9f0341be0a6c960ea9e8db0939e4fa3cdac Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Thu, 24 Feb 2022 23:38:21 -0500 Subject: Decomped CanUseStatusMove() --- src/dungeon_ai_attack.c | 1 - src/dungeon_ai_attack_1.c | 233 ++++++++++++++++++++++++++-------------------- src/moves.c | 4 +- 3 files changed, 134 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 65973a1..835d207 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -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) diff --git a/src/dungeon_ai_attack_1.c b/src/dungeon_ai_attack_1.c index fb088fb..023df14 100644 --- a/src/dungeon_ai_attack_1.c +++ b/src/dungeon_ai_attack_1.c @@ -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; +} diff --git a/src/moves.c b/src/moves.c index a7caed6..ed1f38d 100644 --- a/src/moves.c +++ b/src/moves.c @@ -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) -- cgit v1.2.3