diff options
Diffstat (limited to 'src/status_checker.c')
-rw-r--r-- | src/status_checker.c | 402 |
1 files changed, 385 insertions, 17 deletions
diff --git a/src/status_checker.c b/src/status_checker.c index 07d6c7f..f2ea0f8 100644 --- a/src/status_checker.c +++ b/src/status_checker.c @@ -11,6 +11,7 @@ #include "dungeon_util.h" #include "dungeon_visibility.h" #include "map.h" +#include "moves.h" #include "number_util.h" #include "status_checks_1.h" #include "tile_types.h" @@ -97,6 +98,10 @@ const u8 gDungeonCamouflageTypes[76] = { TYPE_ROCK }; +extern bool8 HasLastUsedMove(struct PokemonMove *moves); +extern bool8 HasDisabledMove(struct PokemonMove *moves); +extern bool8 LastMoveOutOfPP(struct PokemonMove *moves); + bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct PokemonMove *move) { struct DungeonEntityData *pokemonData = pokemon->entityData; @@ -130,13 +135,13 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo case MOVE_HOWL: case MOVE_MEDITATE: case MOVE_SHARPEN: - if (pokemonData->attackStage >= MAX_STAT_STAGE) + if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE) { return FALSE; } break; case MOVE_BELLY_DRUM: - if (pokemonData->attackStage >= MAX_STAT_STAGE || RoundUpFixedPoint(pokemonData->belly) <= 0) + if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE || RoundUpFixedPoint(pokemonData->belly) <= 0) { return FALSE; } @@ -147,7 +152,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo case MOVE_HARDEN: case MOVE_IRON_DEFENSE: case MOVE_WITHDRAW: - if (pokemonData->defenseStage >= MAX_STAT_STAGE) + if (pokemonData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE) { return FALSE; } @@ -182,7 +187,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_COSMIC_POWER: - if (pokemonData->defenseStage >= MAX_STAT_STAGE && pokemonData->specialDefenseStage >= MAX_STAT_STAGE) + if (pokemonData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE && pokemonData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] >= MAX_STAT_STAGE) { return FALSE; } @@ -212,7 +217,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_MINIMIZE: - if (pokemonData->evasionStage >= MAX_STAT_STAGE) + if (pokemonData->accuracyStages[STAT_STAGE_EVASION] >= MAX_STAT_STAGE) { return FALSE; } @@ -243,7 +248,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_BULK_UP: - if (pokemonData->attackStage >= MAX_STAT_STAGE && pokemonData->defenseStage >= MAX_STAT_STAGE) + if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE && pokemonData->defenseStages[STAT_STAGE_DEFENSE] >= MAX_STAT_STAGE) { return FALSE; } @@ -255,7 +260,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_TAIL_GLOW: - if (pokemonData->specialAttackStage >= MAX_STAT_STAGE) + if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] >= MAX_STAT_STAGE) { return FALSE; } @@ -279,7 +284,7 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_DRAGON_DANCE: - if (pokemonData->attackStage >= MAX_STAT_STAGE && pokemon->entityData->movementSpeed >= MAX_MOVEMENT_SPEED) + if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE && pokemon->entityData->movementSpeed >= MAX_MOVEMENT_SPEED) { return FALSE; } @@ -409,19 +414,19 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_DOUBLE_TEAM: - if (pokemonData->evasionStage >= MAX_STAT_STAGE) + if (pokemonData->accuracyStages[STAT_STAGE_EVASION] >= MAX_STAT_STAGE) { return FALSE; } break; case MOVE_GROWTH: - if (pokemonData->specialAttackStage >= MAX_STAT_STAGE) + if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] >= MAX_STAT_STAGE) { return FALSE; } break; case MOVE_SWORDS_DANCE: - if (pokemonData->attackStage >= MAX_STAT_STAGE) + if (pokemonData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE) { return FALSE; } @@ -445,12 +450,12 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } break; case MOVE_CALM_MIND: - if (pokemonData->specialAttackStage < MAX_STAT_STAGE) + if (pokemonData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE) { break; } case MOVE_AMNESIA: - if (pokemonData->specialDefenseStage >= MAX_STAT_STAGE) + if (pokemonData->defenseStages[STAT_STAGE_SPECIAL_DEFENSE] >= MAX_STAT_STAGE) { return FALSE; } @@ -492,11 +497,11 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo struct DungeonEntity *target = gDungeonGlobalData->wildPokemon[i]; if (EntityExists(target) && target != pokemon && CanSee(pokemon, target)) { - if (target->entityData->attackStage >= MAX_STAT_STAGE) + if (target->entityData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE) { continue; } - if (target->entityData->specialAttackStage < MAX_STAT_STAGE) + if (target->entityData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE) { break; } @@ -516,11 +521,11 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo struct DungeonEntity *target = gDungeonGlobalData->teamPokemon[i]; if (EntityExists(target) && target != pokemon && CanSee(pokemon, target)) { - if (target->entityData->attackStage >= MAX_STAT_STAGE) + if (target->entityData->attackStages[STAT_STAGE_ATTACK] >= MAX_STAT_STAGE) { continue; } - if (target->entityData->specialAttackStage < MAX_STAT_STAGE) + if (target->entityData->attackStages[STAT_STAGE_SPECIAL_ATTACK] < MAX_STAT_STAGE) { break; } @@ -535,3 +540,366 @@ bool8 CanUseOnSelfWithStatusChecker(struct DungeonEntity *pokemon, struct Pokemo } 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 (LastMoveOutOfPP(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->type1 == TYPE_GHOST || targetData->type2 == 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; +} |