mirror of
https://github.com/pret/pmd-red.git
synced 2026-04-24 23:17:03 -05:00
split status_checker into status_actions and move_checks
This commit is contained in:
parent
ad30396f48
commit
29b6e36457
10
include/move_checks.h
Normal file
10
include/move_checks.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef GUARD_MOVE_CHECKS_H
|
||||
#define GUARD_MOVE_CHECKS_H
|
||||
|
||||
bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move);
|
||||
bool8 CanUseOnTargetWithStatusChecker(struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move);
|
||||
bool8 HasDisabledMove(struct PokemonMove *moves);
|
||||
bool8 LastUsedMoveOutOfPP(struct PokemonMove *moves);
|
||||
bool8 HasLastUsedMove(struct PokemonMove *moves);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef GUARD_STATUS_CHECKER_H
|
||||
#define GUARD_STATUS_CHECKER_H
|
||||
#ifndef GUARD_STATUS_ACTIONS_H
|
||||
#define GUARD_STATUS_ACTIONS_H
|
||||
|
||||
#include "constants/move.h"
|
||||
#include "dungeon_entity.h"
|
||||
|
|
@ -52,10 +52,5 @@ bool8 sub_805C468(struct DungeonEntity *pokemon, struct DungeonEntity *target);
|
|||
bool8 StairsOrbAction(struct DungeonEntity *pokemon, struct DungeonEntity *target);
|
||||
bool8 LongtossOrbAction(struct DungeonEntity *pokemon, struct DungeonEntity *target);
|
||||
bool8 PierceOrbAction(struct DungeonEntity *pokemon, struct DungeonEntity *target);
|
||||
bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move);
|
||||
bool8 CanUseOnTargetWithStatusChecker(struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move);
|
||||
bool8 HasDisabledMove(struct PokemonMove *moves);
|
||||
bool8 LastUsedMoveOutOfPP(struct PokemonMove *moves);
|
||||
bool8 HasLastUsedMove(struct PokemonMove *moves);
|
||||
|
||||
#endif
|
||||
|
|
@ -220,7 +220,8 @@ SECTIONS {
|
|||
asm/code_805744C.o(.text);
|
||||
src/code_8057824.o(.text);
|
||||
asm/code_8057824.o(.text);
|
||||
src/status_checker.o(.text);
|
||||
src/status_actions.o(.text);
|
||||
src/move_checks.o(.text);
|
||||
asm/code_805D8C8.o(.text);
|
||||
src/targeting.o(.text);
|
||||
src/code_8069E0C.o(.text);
|
||||
|
|
@ -459,7 +460,7 @@ SECTIONS {
|
|||
data/data_80F4E2C.o(.rodata);
|
||||
src/type_chart.o(.rodata);
|
||||
data/data_80F54B4.o(.rodata);
|
||||
src/status_checker.o(.rodata);
|
||||
src/move_checks.o(.rodata);
|
||||
data/data_80F5668.o(.rodata);
|
||||
src/dungeon_pokemon_attributes.o(.rodata);
|
||||
data/data_80F59C8.o(.rodata);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
#include "dungeon_visibility.h"
|
||||
#include "move_util.h"
|
||||
#include "moves.h"
|
||||
#include "move_checks.h"
|
||||
#include "position_util.h"
|
||||
#include "status_checker.h"
|
||||
#include "status_checks.h"
|
||||
#include "status_checks_1.h"
|
||||
#include "targeting.h"
|
||||
|
|
|
|||
954
src/move_checks.c
Normal file
954
src/move_checks.c
Normal file
|
|
@ -0,0 +1,954 @@
|
|||
#include "global.h"
|
||||
#include "constants/status.h"
|
||||
#include "constants/type.h"
|
||||
#include "constants/weather.h"
|
||||
#include "dungeon_engine.h"
|
||||
#include "dungeon_global_data.h"
|
||||
#include "dungeon_items.h"
|
||||
#include "dungeon_map_access.h"
|
||||
#include "dungeon_pokemon_attributes.h"
|
||||
#include "dungeon_util.h"
|
||||
#include "dungeon_visibility.h"
|
||||
#include "move_checks.h"
|
||||
#include "moves.h"
|
||||
#include "number_util.h"
|
||||
#include "status.h"
|
||||
#include "status_actions.h"
|
||||
#include "status_checks_1.h"
|
||||
#include "team_inventory.h"
|
||||
#include "text_util.h"
|
||||
#include "tile_types.h"
|
||||
#include "trap.h"
|
||||
#include "weather.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
|
||||
};
|
||||
|
||||
|
||||
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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_BELLY_DRUM:
|
||||
if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= 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->defenseStages[STAT_STAGE_DEFENSE] >= 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->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE && pokemonData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] >= 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->accuracyStages[STAT_STAGE_EVASION] >= 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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE && pokemonData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CAMOUFLAGE:
|
||||
if (HasType(pokemon, gDungeonCamouflageTypes[gDungeonGlobalData->tileset]))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TAIL_GLOW:
|
||||
if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] >= 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->attackStages[STAT_STAGE_ATTACK] >= 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(GetMapTileForDungeonEntity_2(pokemon)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_DIG:
|
||||
{
|
||||
struct MapTile *tile = GetMapTileForDungeonEntity_2(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 = GetMapTileForDungeonEntity_2(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->accuracyStages[STAT_STAGE_EVASION] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_GROWTH:
|
||||
if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SWORDS_DANCE:
|
||||
if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= 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->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MOVE_AMNESIA:
|
||||
if (pokemonData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] >= 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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (target->entityData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < 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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (target->entityData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == MAX_TEAM_MEMBERS)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 CanUseOnTargetWithStatusChecker(struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move)
|
||||
{
|
||||
struct DungeonEntityData *userData = user->entityData;
|
||||
struct DungeonEntityData *targetData = target->entityData;
|
||||
s32 i;
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_FROZEN && MoveCannotHitFrozen(move))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
switch (move->moveID)
|
||||
{
|
||||
case MOVE_GRASSWHISTLE:
|
||||
case MOVE_HYPNOSIS:
|
||||
case MOVE_LOVELY_KISS:
|
||||
case MOVE_SING:
|
||||
case MOVE_SLEEP_POWDER:
|
||||
case MOVE_SPORE:
|
||||
if (IsSleeping(target))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_YAWN:
|
||||
if (targetData->sleepStatus == SLEEP_STATUS_YAWNING)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (IsSleeping(target))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_NIGHTMARE:
|
||||
if (targetData->sleepStatus == SLEEP_STATUS_NIGHTMARE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SWEET_SCENT:
|
||||
if (targetData->accuracyStages[STAT_STAGE_EVASION] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CHARM:
|
||||
if (targetData->attackMultipliers[STAT_STAGE_ATTACK] < STAT_MULTIPLIER_THRESHOLD)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ENCORE:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_ENCORE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!HasLastUsedMove(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SUPER_FANG:
|
||||
if (targetData->HP <= 1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_PAIN_SPLIT:
|
||||
if (targetData->HP <= userData->HP)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TORMENT:
|
||||
if (HasDisabledMove(targetData->moves) || !HasLastUsedMove(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_COTTON_SPORE:
|
||||
case MOVE_SCARY_FACE:
|
||||
case MOVE_STRING_SHOT:
|
||||
if (target->entityData->movementSpeed <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SCREECH:
|
||||
if (targetData->defenseMultipliers[STAT_STAGE_DEFENSE] < STAT_MULTIPLIER_THRESHOLD)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FAKE_TEARS:
|
||||
if (targetData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SPITE:
|
||||
if (LastUsedMoveOutOfPP(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SMOKESCREEN:
|
||||
if (targetData->moveStatus == MOVE_STATUS_WHIFFER)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_MEMENTO:
|
||||
if (targetData->attackMultipliers[STAT_STAGE_ATTACK] < STAT_MULTIPLIER_THRESHOLD &&
|
||||
targetData->attackMultipliers[STAT_STAGE_SPECIAL_ATTACK] < STAT_MULTIPLIER_THRESHOLD)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_WILL_O_WISP:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_BURNED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FORESIGHT:
|
||||
case MOVE_ODOR_SLEUTH:
|
||||
if (targetData->types[0] == TYPE_GHOST || targetData->types[1] == TYPE_GHOST)
|
||||
{
|
||||
if (!targetData->exposedStatus)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetData->accuracyStages[STAT_STAGE_EVASION] <= DEFAULT_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_DISABLE:
|
||||
case MOVE_GLARE:
|
||||
case MOVE_STUN_SPORE:
|
||||
case MOVE_THUNDER_WAVE:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_PARALYZED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ENDEAVOR:
|
||||
if (targetData->HP - userData->HP <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_LEER:
|
||||
case MOVE_TAIL_WHIP:
|
||||
if (targetData->defenseStages[STAT_STAGE_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_METAL_SOUND:
|
||||
if (targetData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TICKLE:
|
||||
if (targetData->attackStages[STAT_STAGE_ATTACK] <= 0 &&
|
||||
targetData->defenseStages[STAT_STAGE_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_BLOCK:
|
||||
case MOVE_MEAN_LOOK:
|
||||
case MOVE_SPIDER_WEB:
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_IMMOBILIZED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_HAZE:
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (targetData->attackStages[i] < DEFAULT_STAT_STAGE) break;
|
||||
if (targetData->defenseStages[i] < DEFAULT_STAT_STAGE) break;
|
||||
if (targetData->accuracyStages[i] < DEFAULT_STAT_STAGE ||
|
||||
targetData->attackMultipliers[i] < DEFAULT_STAT_MULTIPLIER ||
|
||||
targetData->defenseMultipliers[i] < DEFAULT_STAT_MULTIPLIER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOVE_UPROAR:
|
||||
if (targetData->sleepStatus == SLEEP_STATUS_SLEEPLESS)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_PSYCH_UP:
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (userData->attackStages[i] < targetData->attackStages[i]) break;
|
||||
if (userData->defenseStages[i] < targetData->defenseStages[i] ||
|
||||
userData->accuracyStages[i] < targetData->accuracyStages[i] ||
|
||||
userData->attackMultipliers[i] < targetData->attackMultipliers[i] ||
|
||||
userData->defenseMultipliers[i] < targetData->defenseMultipliers[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOVE_FLASH:
|
||||
case MOVE_KINESIS:
|
||||
case MOVE_SAND_ATTACK:
|
||||
if (targetData->accuracyStages[STAT_STAGE_ACCURACY] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TAUNT:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_TAUNTED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TRICK:
|
||||
if (!(userData->heldItem.itemFlags & ITEM_FLAG_EXISTS) ||
|
||||
!(targetData->heldItem.itemFlags & ITEM_FLAG_EXISTS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_KNOCK_OFF:
|
||||
if (!(targetData->heldItem.itemFlags & ITEM_FLAG_EXISTS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FEATHERDANCE:
|
||||
case MOVE_GROWL:
|
||||
if (targetData->attackStages[STAT_STAGE_ATTACK] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ROLE_PLAY:
|
||||
if (userData->abilities[0] == targetData->abilities[0] &&
|
||||
userData->abilities[1] == targetData->abilities[1])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CURSE:
|
||||
if (HasType(user, TYPE_GHOST))
|
||||
{
|
||||
if (targetData->waitingStatus == WAITING_STATUS_CURSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (userData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE &&
|
||||
userData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_IMPRISON:
|
||||
case MOVE_OBSERVER:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_PAUSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FALSE_SWIPE:
|
||||
if (targetData->HP <= 1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_LEECH_SEED:
|
||||
if (targetData->linkedStatus == LINKED_STATUS_LEECH_SEED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_PERISH_SONG:
|
||||
if (targetData->perishSongTimer != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_MIMIC:
|
||||
case MOVE_SKETCH:
|
||||
if (!HasLastUsedMove(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ATTRACT:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_INFATUATED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_WRAP:
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_WRAPPED_AROUND_FOE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_WRAPPED_BY_FOE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TOXIC:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_BADLY_POISONED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_POISON_GAS:
|
||||
case MOVE_POISONPOWDER:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_POISONED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_BADLY_POISONED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CONFUSE_RAY:
|
||||
case MOVE_FLATTER:
|
||||
case MOVE_SUPERSONIC:
|
||||
case MOVE_SWAGGER:
|
||||
case MOVE_SWEET_KISS:
|
||||
case MOVE_TEETER_DANCE:
|
||||
case MOVE_TOTTER:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_CONFUSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 HasDisabledMove(struct PokemonMove *moves)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i].moveFlags & MOVE_FLAG_EXISTS && moves[i].moveFlags & MOVE_FLAG_DISABLED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (moves[STRUGGLE_MOVE_INDEX].moveFlags & MOVE_FLAG_DISABLED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 LastUsedMoveOutOfPP(struct PokemonMove *moves)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i].moveFlags & MOVE_FLAG_EXISTS &&
|
||||
moves[i].moveFlags & MOVE_FLAG_LAST_USED &&
|
||||
moves[i].PP == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 HasLastUsedMove(struct PokemonMove *moves)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i].moveFlags & MOVE_FLAG_EXISTS && moves[i].moveFlags & MOVE_FLAG_LAST_USED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (moves[STRUGGLE_MOVE_INDEX].moveFlags & MOVE_FLAG_LAST_USED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#include "global.h"
|
||||
#include "status_checker.h"
|
||||
#include "status_actions.h"
|
||||
|
||||
#include "code_80521D0.h"
|
||||
#include "code_8077274_1.h"
|
||||
|
|
@ -146,6 +146,7 @@ extern u8 *gPtrForecastPreventsTypeSwitchMessage[];
|
|||
extern u8 *gUnknown_80FEB08[];
|
||||
extern u8 gUnknown_202DE58[];
|
||||
extern s16 gUnknown_80F4E08;
|
||||
extern u8 gDungeonCamouflageTypes[76];
|
||||
|
||||
struct Position_Alt
|
||||
{
|
||||
|
|
@ -156,85 +157,6 @@ struct Position_Alt
|
|||
} temp;
|
||||
};
|
||||
|
||||
// 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 s16 gUnknown_80F4DC6;
|
||||
extern u8 *gUnknown_80FEFF4[];
|
||||
|
|
@ -1382,854 +1304,3 @@ bool8 PierceOrbAction(struct DungeonEntity *pokemon, struct DungeonEntity *targe
|
|||
PierceStatusTarget(pokemon, target);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_BELLY_DRUM:
|
||||
if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= 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->defenseStages[STAT_STAGE_DEFENSE] >= 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->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE && pokemonData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] >= 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->accuracyStages[STAT_STAGE_EVASION] >= 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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE && pokemonData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CAMOUFLAGE:
|
||||
if (HasType(pokemon, gDungeonCamouflageTypes[gDungeonGlobalData->tileset]))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TAIL_GLOW:
|
||||
if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] >= 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->attackStages[STAT_STAGE_ATTACK] >= 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(GetMapTileForDungeonEntity_2(pokemon)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_DIG:
|
||||
{
|
||||
struct MapTile *tile = GetMapTileForDungeonEntity_2(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 = GetMapTileForDungeonEntity_2(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->accuracyStages[STAT_STAGE_EVASION] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_GROWTH:
|
||||
if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SWORDS_DANCE:
|
||||
if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= 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->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MOVE_AMNESIA:
|
||||
if (pokemonData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] >= 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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (target->entityData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < 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->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (target->entityData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == MAX_TEAM_MEMBERS)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 CanUseOnTargetWithStatusChecker(struct DungeonEntity *user, struct DungeonEntity *target, struct PokemonMove *move)
|
||||
{
|
||||
struct DungeonEntityData *userData = user->entityData;
|
||||
struct DungeonEntityData *targetData = target->entityData;
|
||||
s32 i;
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_FROZEN && MoveCannotHitFrozen(move))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
switch (move->moveID)
|
||||
{
|
||||
case MOVE_GRASSWHISTLE:
|
||||
case MOVE_HYPNOSIS:
|
||||
case MOVE_LOVELY_KISS:
|
||||
case MOVE_SING:
|
||||
case MOVE_SLEEP_POWDER:
|
||||
case MOVE_SPORE:
|
||||
if (IsSleeping(target))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_YAWN:
|
||||
if (targetData->sleepStatus == SLEEP_STATUS_YAWNING)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (IsSleeping(target))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_NIGHTMARE:
|
||||
if (targetData->sleepStatus == SLEEP_STATUS_NIGHTMARE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SWEET_SCENT:
|
||||
if (targetData->accuracyStages[STAT_STAGE_EVASION] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CHARM:
|
||||
if (targetData->attackMultipliers[STAT_STAGE_ATTACK] < STAT_MULTIPLIER_THRESHOLD)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ENCORE:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_ENCORE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!HasLastUsedMove(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SUPER_FANG:
|
||||
if (targetData->HP <= 1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_PAIN_SPLIT:
|
||||
if (targetData->HP <= userData->HP)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TORMENT:
|
||||
if (HasDisabledMove(targetData->moves) || !HasLastUsedMove(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_COTTON_SPORE:
|
||||
case MOVE_SCARY_FACE:
|
||||
case MOVE_STRING_SHOT:
|
||||
if (target->entityData->movementSpeed <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SCREECH:
|
||||
if (targetData->defenseMultipliers[STAT_STAGE_DEFENSE] < STAT_MULTIPLIER_THRESHOLD)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FAKE_TEARS:
|
||||
if (targetData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SPITE:
|
||||
if (LastUsedMoveOutOfPP(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_SMOKESCREEN:
|
||||
if (targetData->moveStatus == MOVE_STATUS_WHIFFER)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_MEMENTO:
|
||||
if (targetData->attackMultipliers[STAT_STAGE_ATTACK] < STAT_MULTIPLIER_THRESHOLD &&
|
||||
targetData->attackMultipliers[STAT_STAGE_SPECIAL_ATTACK] < STAT_MULTIPLIER_THRESHOLD)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_WILL_O_WISP:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_BURNED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FORESIGHT:
|
||||
case MOVE_ODOR_SLEUTH:
|
||||
if (targetData->types[0] == TYPE_GHOST || targetData->types[1] == TYPE_GHOST)
|
||||
{
|
||||
if (!targetData->exposedStatus)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetData->accuracyStages[STAT_STAGE_EVASION] <= DEFAULT_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_DISABLE:
|
||||
case MOVE_GLARE:
|
||||
case MOVE_STUN_SPORE:
|
||||
case MOVE_THUNDER_WAVE:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_PARALYZED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ENDEAVOR:
|
||||
if (targetData->HP - userData->HP <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_LEER:
|
||||
case MOVE_TAIL_WHIP:
|
||||
if (targetData->defenseStages[STAT_STAGE_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_METAL_SOUND:
|
||||
if (targetData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TICKLE:
|
||||
if (targetData->attackStages[STAT_STAGE_ATTACK] <= 0 &&
|
||||
targetData->defenseStages[STAT_STAGE_DEFENSE] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_BLOCK:
|
||||
case MOVE_MEAN_LOOK:
|
||||
case MOVE_SPIDER_WEB:
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_IMMOBILIZED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_HAZE:
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (targetData->attackStages[i] < DEFAULT_STAT_STAGE) break;
|
||||
if (targetData->defenseStages[i] < DEFAULT_STAT_STAGE) break;
|
||||
if (targetData->accuracyStages[i] < DEFAULT_STAT_STAGE ||
|
||||
targetData->attackMultipliers[i] < DEFAULT_STAT_MULTIPLIER ||
|
||||
targetData->defenseMultipliers[i] < DEFAULT_STAT_MULTIPLIER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOVE_UPROAR:
|
||||
if (targetData->sleepStatus == SLEEP_STATUS_SLEEPLESS)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_PSYCH_UP:
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (userData->attackStages[i] < targetData->attackStages[i]) break;
|
||||
if (userData->defenseStages[i] < targetData->defenseStages[i] ||
|
||||
userData->accuracyStages[i] < targetData->accuracyStages[i] ||
|
||||
userData->attackMultipliers[i] < targetData->attackMultipliers[i] ||
|
||||
userData->defenseMultipliers[i] < targetData->defenseMultipliers[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOVE_FLASH:
|
||||
case MOVE_KINESIS:
|
||||
case MOVE_SAND_ATTACK:
|
||||
if (targetData->accuracyStages[STAT_STAGE_ACCURACY] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TAUNT:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_TAUNTED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TRICK:
|
||||
if (!(userData->heldItem.itemFlags & ITEM_FLAG_EXISTS) ||
|
||||
!(targetData->heldItem.itemFlags & ITEM_FLAG_EXISTS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_KNOCK_OFF:
|
||||
if (!(targetData->heldItem.itemFlags & ITEM_FLAG_EXISTS))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FEATHERDANCE:
|
||||
case MOVE_GROWL:
|
||||
if (targetData->attackStages[STAT_STAGE_ATTACK] <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ROLE_PLAY:
|
||||
if (userData->abilities[0] == targetData->abilities[0] &&
|
||||
userData->abilities[1] == targetData->abilities[1])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CURSE:
|
||||
if (HasType(user, TYPE_GHOST))
|
||||
{
|
||||
if (targetData->waitingStatus == WAITING_STATUS_CURSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (userData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE &&
|
||||
userData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_IMPRISON:
|
||||
case MOVE_OBSERVER:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_PAUSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_FALSE_SWIPE:
|
||||
if (targetData->HP <= 1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_LEECH_SEED:
|
||||
if (targetData->linkedStatus == LINKED_STATUS_LEECH_SEED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_PERISH_SONG:
|
||||
if (targetData->perishSongTimer != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_MIMIC:
|
||||
case MOVE_SKETCH:
|
||||
if (!HasLastUsedMove(targetData->moves))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_ATTRACT:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_INFATUATED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_WRAP:
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_WRAPPED_AROUND_FOE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (targetData->immobilizeStatus == IMMOBILIZE_STATUS_WRAPPED_BY_FOE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_TOXIC:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_BADLY_POISONED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_POISON_GAS:
|
||||
case MOVE_POISONPOWDER:
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_POISONED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (targetData->nonVolatileStatus == NON_VOLATILE_STATUS_BADLY_POISONED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case MOVE_CONFUSE_RAY:
|
||||
case MOVE_FLATTER:
|
||||
case MOVE_SUPERSONIC:
|
||||
case MOVE_SWAGGER:
|
||||
case MOVE_SWEET_KISS:
|
||||
case MOVE_TEETER_DANCE:
|
||||
case MOVE_TOTTER:
|
||||
if (targetData->volatileStatus == VOLATILE_STATUS_CONFUSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 HasDisabledMove(struct PokemonMove *moves)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i].moveFlags & MOVE_FLAG_EXISTS && moves[i].moveFlags & MOVE_FLAG_DISABLED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (moves[STRUGGLE_MOVE_INDEX].moveFlags & MOVE_FLAG_DISABLED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 LastUsedMoveOutOfPP(struct PokemonMove *moves)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i].moveFlags & MOVE_FLAG_EXISTS &&
|
||||
moves[i].moveFlags & MOVE_FLAG_LAST_USED &&
|
||||
moves[i].PP == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 HasLastUsedMove(struct PokemonMove *moves)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i].moveFlags & MOVE_FLAG_EXISTS && moves[i].moveFlags & MOVE_FLAG_LAST_USED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (moves[STRUGGLE_MOVE_INDEX].moveFlags & MOVE_FLAG_LAST_USED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user