summaryrefslogtreecommitdiff
path: root/src/status_checker.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/status_checker.c')
-rw-r--r--src/status_checker.c402
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;
+}