Merge pull request #145 from AnonymousRandomPerson/main

Added nonmatching for StatusCheckerCheck
This commit is contained in:
AnonymousRandomPerson 2025-07-12 20:24:14 -04:00 committed by GitHub
commit ee2e4b4c71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 527 additions and 26 deletions

View File

@ -3,6 +3,7 @@
.public ApplyDamageAndEffects
.public CalcDamage
.public CanAttackInDirection
.public CanLayTrap
.public CanSeeTarget
.public CeilFixedPoint
.public Conversion2IsActive
@ -19,6 +20,7 @@
.public GetMoveTypeForMonster
.public GetTileAtEntity
.public IsCurrentFixedRoomBossFight
.public IsTileGround
.public LogMessageByIdQuietCheckUserTarget
.public LogMessageByIdWithPopupCheckUserTarget
.public MirrorMoveIsActive
@ -30,10 +32,8 @@
.public abs
.public ov10_022C6322
.public ov29_022E576C
.public CanLayTrap
.public ov29_0230040C
.public ov29_023007DC
.public ov29_02304A48
.public ov29_0230D088
.public IsTileGround
.public ov29_0234B034

View File

@ -23914,6 +23914,7 @@ _0206C8BC: .word DRIVER_WORK
_0206C8C0: .word _022B7340
arm_func_end Dse_SetError2
; https://decomp.me/scratch/C4osO
arm_func_start DseUtil_ByteSwap32
DseUtil_ByteSwap32: ; 0x0206C8C4
mov r3, r0, lsr #0x18
@ -23945,6 +23946,7 @@ _0206C914: .word DRIVER_WORK
_0206C918: .word 0x00007FFF
arm_func_end DseUtil_GetRandomNumber
; https://decomp.me/scratch/KrgBG
arm_func_start DseMem_Init
DseMem_Init: ; 0x0206C91C
mov ip, r1

View File

@ -65,6 +65,7 @@ _02089754: .word 0xFEFEFEFF
_02089758: .word 0x80808080
arm_func_end strcpy
; https://decomp.me/scratch/QI5Xl
arm_func_start strncpy
strncpy: ; 0x0208975C
stmdb sp!, {r3, lr}

View File

@ -490,6 +490,8 @@ ov29_02333044: ; 0x02333044
ldmia sp!, {r3, r4, r5, pc}
arm_func_end ov29_02333044
; https://decomp.me/scratch/TnODN
#ifndef NONMATCHING
arm_func_start StatusCheckerCheck
StatusCheckerCheck: ; 0x02333074
#ifdef JAPAN
@ -1638,3 +1640,4 @@ _02333FA0: .word 0x0000021E
_02333FA4: .word DUNGEON_PTR
_02333FA8: .word ov10_022C6322
arm_func_end StatusCheckerCheck
#endif

View File

@ -21,6 +21,11 @@ enum terrain_type
TERRAIN_TYPE_IMPASSABLE_WALL = 1 << 4, // x10
};
struct monster_slots {
struct entity* party_members[MAX_TEAM_MEMBERS];
struct entity* wild_pokemon[DUNGEON_MAX_WILD_POKEMON];
};
// Dungeon state
struct dungeon {
u8 field_0x0; // 0x0: Initialized to 0x0.
@ -1541,7 +1546,7 @@ struct dungeon {
// The pointers point into the entities array
// 0x12B28 / 0x0: A list of all monster pointers, whether they're used or not
union {
struct entity* party_members[MAX_TEAM_MEMBERS];
struct monster_slots monster_slots;
struct entity* monster_slot_ptrs[DUNGEON_MAX_POKEMON];
};
// 0x12B78 / 0x50: Null-terminated array of pointers to actually active monsters

View File

@ -14,6 +14,7 @@
#define MAX_SPEED_STAGE 4
#define NUM_SPEED_COUNTERS 5
#define MAX_STOCKPILE_STAGE 3
#define NUM_STATS_PER_CATEGORY 2
#define STAT_STAGE_ATK 0
#define STAT_STAGE_SP_ATK 1
@ -38,17 +39,17 @@ struct pixel_position {
// Monster stat modifier info
struct monster_stat_modifiers {
// Stages go from 0-20 inclusive, with normal being 10
s16 offensive_stages[2]; // 0x0: {atk, sp_atk}
s16 defensive_stages[2]; // 0x4: {def, sp_def}
s16 hit_chance_stages[2]; // 0x8: {accuracy, evasion}
s16 offensive_stages[NUM_STATS_PER_CATEGORY]; // 0x0: {atk, sp_atk}
s16 defensive_stages[NUM_STATS_PER_CATEGORY]; // 0x4: {def, sp_def}
s16 hit_chance_stages[NUM_STATS_PER_CATEGORY]; // 0x8: {accuracy, evasion}
s16 flash_fire_boost; // 0xC: can be 0, 1, or 2
u8 field_0xe;
u8 field_0xf;
// Some moves like Screech affect the damage calculation differently than, e.g., Leer
// 0x10: binary fixed-point (8 fraction bits), {atk, sp_atk}; from Charm, Memento, etc.
fx32_8 offensive_multipliers[2];
fx32_8 offensive_multipliers[NUM_STATS_PER_CATEGORY];
// 0x18: binary fixed-point (8 fraction bits), {def, sp_def}; from Screech, etc.
fx32_8 defensive_multipliers[2];
fx32_8 defensive_multipliers[NUM_STATS_PER_CATEGORY];
};
// A bitfield where every bit controls one of the icons that can appear on top of a monster's sprite
@ -328,11 +329,11 @@ struct monster {
struct long_toss_class_status long_toss_class_status; // 0xEE
struct invisible_class_status invisible_class_status; // 0xEF
struct blinker_class_status blinker_class_status; // 0xF1
u8 muzzled; // 0xF3: STATUS_MUZZLED if 1
bool8 muzzled; // 0xF3: STATUS_MUZZLED if 1
u8 muzzled_turns; // 0xF4: Turns left for the status in statuses::muzzled
u8 miracle_eye; // 0xF5: STATUS_MIRACLE_EYE if 1
bool8 miracle_eye; // 0xF5: STATUS_MIRACLE_EYE if 1
u8 miracle_eye_turns; // 0xF6: Turns left for the status in statuses::miracle_eye
u8 magnet_rise; // 0xF7: STATUS_MAGNET_RISE if 1
bool8 magnet_rise; // 0xF7: STATUS_MAGNET_RISE if 1
u8 magnet_rise_turns; // 0xF8: Turns left for the status in statuses::magnet_rise
bool8 power_ears; // 0xF9: STATUS_POWER_EARS
bool8 scanning; // 0xFA: STATUS_SCANNING

View File

@ -1,9 +1,10 @@
#ifndef PMDSKY_OVERLAY_29_02333FAC_H
#define PMDSKY_OVERLAY_29_02333FAC_H
#ifndef PMDSKY_MOVE_CHECKS_H
#define PMDSKY_MOVE_CHECKS_H
#include "dungeon_mode.h"
bool8 StatusCheckerCheck(struct entity *attacker, struct move *move);
// Checks if an entity pointer points to a valid entity (not entity type 0, which represents no entity).
bool8 EntityIsValid__02333FAC(struct entity *entity);
#endif //PMDSKY_OVERLAY_29_02333FAC_H
#endif //PMDSKY_MOVE_CHECKS_H

20
include/tileset.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef PMDSKY_TILESET_H
#define PMDSKY_TILESET_H
#include "enums.h"
struct tileset_property {
s32 field_0x0;
u8 field_0x4;
u8 field_0x5;
enum type_id camouflage_type;
u16 nature_power_variant;
u8 field_0xa;
// 0xB: True if this is a water tileset. If so, a different kind of shadow will be displayed
// under monsters in dungeons, drought orbs won't work and Dive can be used anywhere.
bool8 is_water_tileset;
};
extern struct tileset_property TILESET_PROPERTIES[199];
#endif //PMDSKY_TILESET_H

View File

@ -493,7 +493,7 @@ Overlay OVY_29
Object asm/overlay_29_0232E864.o
Object src/overlay_29_023329E8.o
Object asm/overlay_29_02332A0C.o
Object src/overlay_29_02333FAC.o
Object src/move_checks.o
Object asm/overlay_29_02333FD0.o
Object src/overlay_29_023350D8.o
Object asm/overlay_29_023350FC.o

View File

@ -9,6 +9,7 @@
#include "dungeon_util_static.h"
#include "dungeon_visibility.h"
#include "main_0208655C.h"
#include "move_checks.h"
#include "move_data.h"
#include "moves_2.h"
#include "moves_3.h"
@ -21,7 +22,6 @@ extern u8 AI_POTENTIAL_ATTACK_TARGET_DIRECTIONS[NUM_DIRECTIONS];
extern s32 AI_POTENTIAL_ATTACK_TARGET_WEIGHTS[NUM_DIRECTIONS];
extern struct entity *AI_POTENTIAL_ATTACK_TARGETS[NUM_DIRECTIONS];
extern bool8 StatusCheckerCheck(struct entity *attacker, struct move *move);
extern bool8 CanAttackInDirection(struct entity *monster, s32 direction);
extern s32 TryAddTargetToAiTargetList(s32 current_num_targets, s32 move_ai_range, struct entity *user, struct entity *target, struct move *move, bool8 check_all_conditions);
extern bool8 IsAiTargetEligible(s32 move_ai_range, struct entity *user, struct entity *target, struct move *move, bool8 check_all_conditions);

View File

@ -9,6 +9,7 @@
#include "dungeon_capabilities_4.h"
#include "dungeon_misc.h"
#include "dungeon_mode.h"
#include "dungeon_move.h"
#include "dungeon_parameters.h"
#include "dungeon_pokemon_attributes.h"
#include "dungeon_pokemon_attributes_1.h"

476
src/move_checks.c Normal file
View File

@ -0,0 +1,476 @@
#include "move_checks.h"
#include "dungeon_logic.h"
#include "dungeon_logic_3.h"
#include "dungeon_util_static.h"
#include "dungeon_visibility.h"
#include "number_util.h"
#include "tileset.h"
extern struct dungeon* DUNGEON_PTR[];
extern enum weather_id GetApparentWeather(struct entity *entity);
extern bool8 MirrorMoveIsActive(struct entity *entity);
extern bool8 MistIsActive(struct entity *entity);
extern bool8 IsCurrentFixedRoomBossFight();
extern bool8 CanLayTrap(struct position *pos);
extern bool8 Conversion2IsActive(struct entity *entity);
extern bool8 HasLowHealth(struct entity *entity);
extern struct tile* GetTileAtEntity(struct entity *entity);
extern bool8 IsTileGround(struct tile *tile);
// https://decomp.me/scratch/TnODN
#ifdef NONMATCHING
bool8 StatusCheckerCheck(struct entity *attacker, struct move *move)
{
struct monster *pokemon_info = GetEntInfo(attacker);
switch (move->id)
{
case MOVE_HAIL:
if (GetApparentWeather(attacker) == WEATHER_HAIL)
return FALSE;
break;
case MOVE_RAGE:
if (pokemon_info->bide_class_status.bide == STATUS_TWO_TURN_ENRAGED)
return FALSE;
break;
case MOVE_COUNTER:
case MOVE_PAYBACK:
case MOVE_PURSUIT:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_COUNTER)
return FALSE;
break;
case MOVE_MIRROR_MOVE:
if (MirrorMoveIsActive(attacker))
return FALSE;
break;
case MOVE_HOWL:
case MOVE_MEDITATE:
case MOVE_SHARPEN:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_ATK] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_BELLY_DRUM:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_ATK] > MAX_STAT_STAGE - 1 || CeilFixedPoint(pokemon_info->belly) < 1)
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 (pokemon_info->stat_modifiers.defensive_stages[STAT_STAGE_DEF] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_AMNESIA:
if (pokemon_info->stat_modifiers.defensive_stages[STAT_STAGE_SP_DEF] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_BIDE:
case MOVE_REVENGE:
case MOVE_AVALANCHE:
if (pokemon_info->bide_class_status.bide == STATUS_TWO_TURN_BIDE)
return FALSE;
break;
case MOVE_AGILITY:
case MOVE_ROCK_POLISH:
case MOVE_TAILWIND:
if (GetEntInfo(attacker)->speed_stage > MAX_SPEED_STAGE - 1)
return FALSE;
break;
case MOVE_LOCK_ON:
case MOVE_MIND_READER:
if (pokemon_info->sure_shot_class_status.sure_shot == STATUS_SURE_SHOT_SURE_SHOT)
return FALSE;
break;
case MOVE_COSMIC_POWER:
if (pokemon_info->stat_modifiers.defensive_stages[STAT_STAGE_DEF] > MAX_STAT_STAGE - 1 && pokemon_info->stat_modifiers.defensive_stages[STAT_STAGE_SP_DEF] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_ENDURE:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_ENDURING)
return FALSE;
break;
case MOVE_CHARGE:
if (pokemon_info->bide_class_status.bide == STATUS_TWO_TURN_CHARGING)
return FALSE;
break;
case MOVE_MIST:
if (MistIsActive(attacker))
return FALSE;
break;
case MOVE_LIGHT_SCREEN:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_LIGHT_SCREEN)
return FALSE;
break;
case MOVE_MINIMIZE:
if (pokemon_info->stat_modifiers.hit_chance_stages[STAT_STAGE_EVASION] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_INGRAIN:
{
if (pokemon_info->frozen_class_status.freeze == STATUS_FROZEN_INGRAIN)
return FALSE;
s32 max_hp = Min(999, pokemon_info->max_hp_stat + pokemon_info->max_hp_boost);
if (max_hp / 2 < pokemon_info->hp)
return FALSE;
break;
}
case MOVE_SWALLOW:
{
s32 max_hp = Min(999, pokemon_info->max_hp_stat + pokemon_info->max_hp_boost);
if (max_hp <= pokemon_info->hp || pokemon_info->stockpile_stage == 0)
return FALSE;
break;
}
case MOVE_SPIT_UP:
if (pokemon_info->stockpile_stage == 0)
return FALSE;
break;
case MOVE_DOOM_DESIRE:
case MOVE_FUTURE_SIGHT:
if (pokemon_info->sure_shot_class_status.sure_shot == STATUS_SURE_SHOT_SET_DAMAGE)
return FALSE;
break;
case MOVE_BULK_UP:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_ATK] > MAX_STAT_STAGE - 1 && pokemon_info->stat_modifiers.defensive_stages[STAT_STAGE_DEF] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_CAMOUFLAGE:
if (MonsterIsType(attacker, TILESET_PROPERTIES[DUNGEON_PTR[0]->gen_info.tileset_id].camouflage_type))
return FALSE;
break;
case MOVE_TAIL_GLOW:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] > MAX_STAT_STAGE - 1)
return FALSE;
break;
case MOVE_DESTINY_BOND:
if (pokemon_info->leech_seed_class_status.leech_seed == STATUS_LEECH_SEED_DESTINY_BOND)
return FALSE;
break;
case MOVE_MIRROR_COAT:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_MIRROR_COAT)
return FALSE;
break;
case MOVE_REFLECT:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_REFLECT)
return FALSE;
break;
case MOVE_DRAGON_DANCE:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_ATK] > MAX_STAT_STAGE - 1 && GetEntInfo(attacker)->speed_stage > MAX_SPEED_STAGE - 1)
return FALSE;
break;
case MOVE_MAGIC_COAT:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_MAGIC_COAT)
return FALSE;
break;
case MOVE_DETECT:
case MOVE_PROTECT:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_PROTECT)
return FALSE;
break;
case MOVE_RAIN_DANCE:
if (GetApparentWeather(attacker) == WEATHER_RAIN)
return FALSE;
break;
case MOVE_SANDSTORM:
if (GetApparentWeather(attacker) == WEATHER_SANDSTORM)
return FALSE;
break;
case MOVE_SUNNY_DAY:
if (GetApparentWeather(attacker) == WEATHER_SUNNY)
return FALSE;
break;
case MOVE_SAFEGUARD:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_SAFEGUARD)
return FALSE;
break;
case MOVE_INVISIFY:
if (pokemon_info->invisible_class_status.status == STATUS_INVISIBLE_INVISIBLE)
return FALSE;
break;
case MOVE_FOCUS_ENERGY:
if (pokemon_info->sure_shot_class_status.sure_shot == STATUS_SURE_SHOT_FOCUS_ENERGY)
return FALSE;
break;
case MOVE_TAKEAWAY:
if (ItemExists(pokemon_info->held_item.flags))
return FALSE;
break;
case MOVE_REST:
if (!HasLowHealth(attacker) && !MonsterHasNegativeStatus(attacker, FALSE))
return FALSE;
break;
case MOVE_DIVE:
if (IsTileGround(GetTileAtEntity(attacker)))
return FALSE;
break;
case MOVE_DIG:
{
struct tile *tile = GetTileAtEntity(attacker);
if (!IsTileGround(tile) || (tile->terrain_flags & (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY)) != TERRAIN_TYPE_NORMAL)
return FALSE;
break;
}
case MOVE_TRAP_BUSTER:
{
struct entity *object = GetTileAtEntity(attacker)->object;
if (object == NULL)
return FALSE;
if (object->type != ENTITY_TRAP)
return FALSE;
break;
}
case MOVE_MUD_SPORT:
if (DUNGEON_PTR[0]->mud_sport_turns > 0)
return FALSE;
break;
case MOVE_WATER_SPORT:
if (DUNGEON_PTR[0]->water_sport_turns > 0)
return FALSE;
break;
case MOVE_GRUDGE:
if (pokemon_info->grudge)
return FALSE;
break;
case MOVE_DECOY_MAKER:
case MOVE_FOLLOW_ME:
case MOVE_SUBSTITUTE:
if (DUNGEON_PTR[0]->decoy_is_active)
return FALSE;
break;
case MOVE_STOCKPILE:
if (pokemon_info->stockpile_stage >= MAX_STOCKPILE_STAGE)
return FALSE;
break;
case MOVE_CLEANSE:
if (ItemExists(pokemon_info->held_item.flags) && !ItemSticky(pokemon_info->held_item.flags))
return FALSE;
break;
case MOVE_DOUBLE_TEAM:
if (pokemon_info->stat_modifiers.hit_chance_stages[STAT_STAGE_EVASION] >= MAX_STAT_STAGE)
return FALSE;
break;
case MOVE_GROWTH:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] >= MAX_STAT_STAGE)
return FALSE;
break;
case MOVE_SWORDS_DANCE:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_ATK] >= MAX_STAT_STAGE)
return FALSE;
break;
case MOVE_WISH:
if (pokemon_info->is_not_team_member)
return FALSE;
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_WISH)
return FALSE;
break;
case MOVE_TRANSFORM:
if (pokemon_info->invisible_class_status.status == STATUS_INVISIBLE_TRANSFORMED)
return FALSE;
if (IsCurrentFixedRoomBossFight())
return FALSE;
break;
case MOVE_SPIKES:
case MOVE_STEALTH_ROCK:
case MOVE_TOXIC_SPIKES:
if (!CanLayTrap(&attacker->pos))
return FALSE;
break;
case MOVE_CALM_MIND:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] >= MAX_STAT_STAGE && pokemon_info->stat_modifiers.defensive_stages[STAT_STAGE_SP_DEF] >= MAX_STAT_STAGE)
return FALSE;
break;
case MOVE_SNATCH:
if (pokemon_info->curse_class_status.curse == STATUS_CURSE_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 (IsCurrentFixedRoomBossFight())
return FALSE;
break;
case MOVE_CONVERSION_2:
if (Conversion2IsActive(attacker))
return FALSE;
break;
case MOVE_HELPING_HAND:
if (pokemon_info->is_not_team_member)
{
s32 i;
for (i = 0; i < DUNGEON_MAX_WILD_POKEMON; i++)
{
struct entity *target = DUNGEON_PTR[0]->monster_slots.wild_pokemon[i];
if (EntityIsValid__02333FAC(target) && target != attacker && CanSeeTarget(attacker, target))
{
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_ATK] >= MAX_STAT_STAGE)
continue;
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] < MAX_STAT_STAGE)
break;
}
}
if (i == DUNGEON_MAX_WILD_POKEMON)
return FALSE;
}
else
{
s32 i;
for (i = 0; i < MAX_TEAM_MEMBERS; i++)
{
struct entity *target = DUNGEON_PTR[0]->monster_slots.party_members[i];
if (EntityIsValid__02333FAC(target) && target != attacker && CanSeeTarget(attacker, target))
{
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_ATK] >= MAX_STAT_STAGE)
continue;
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] < MAX_STAT_STAGE)
break;
}
}
if (i == MAX_TEAM_MEMBERS)
return FALSE;
}
break;
case MOVE_AQUA_RING:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_AQUA_RING)
return FALSE;
break;
case MOVE_LUCKY_CHANT:
if (pokemon_info->is_not_team_member)
{
s32 i;
for (i = 0; i < DUNGEON_MAX_WILD_POKEMON; i++)
{
struct entity *target = DUNGEON_PTR[0]->monster_slots.wild_pokemon[i];
if (EntityIsValid__02333FAC(target) && target != attacker && CanSeeTarget(attacker, target))
{
if (GetEntInfo(target)->reflect_class_status.reflect != STATUS_REFLECT_LUCKY_CHANT)
break;
}
}
if (i == DUNGEON_MAX_WILD_POKEMON)
return FALSE;
}
else
{
s32 i;
for (i = 0; i < MAX_TEAM_MEMBERS; i++)
{
struct entity *target = DUNGEON_PTR[0]->monster_slots.party_members[i];
if (EntityIsValid__02333FAC(target) && target != attacker && CanSeeTarget(attacker, target))
{
if (GetEntInfo(target)->reflect_class_status.reflect != STATUS_REFLECT_LUCKY_CHANT)
break;
}
}
if (i == MAX_TEAM_MEMBERS)
return FALSE;
}
break;
case MOVE_PSYCHO_SHIFT:
if (!MonsterHasNegativeStatus(attacker, FALSE))
return FALSE;
break;
case MOVE_ACUPRESSURE:
if (pokemon_info->is_not_team_member)
{
s32 i;
for (i = 0; i < DUNGEON_MAX_WILD_POKEMON; i++)
{
struct entity *target = DUNGEON_PTR[0]->monster_slots.wild_pokemon[i];
if (EntityIsValid__02333FAC(target) && target != attacker && CanSeeTarget(attacker, target))
{
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_ATK] < MAX_STAT_STAGE)
break;
if (GetEntInfo(target)->stat_modifiers.defensive_stages[STAT_STAGE_DEF] < MAX_STAT_STAGE)
break;
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] < MAX_STAT_STAGE)
break;
if (GetEntInfo(target)->stat_modifiers.defensive_stages[STAT_STAGE_SP_DEF] < MAX_STAT_STAGE)
break;
}
}
if (i == DUNGEON_MAX_WILD_POKEMON)
return FALSE;
}
else
{
s32 i;
for (i = 0; i < MAX_TEAM_MEMBERS; i++)
{
struct entity *target = DUNGEON_PTR[0]->monster_slots.party_members[i];
if (EntityIsValid__02333FAC(target) && target != attacker && CanSeeTarget(attacker, target))
{
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_ATK] < MAX_STAT_STAGE)
break;
if (GetEntInfo(target)->stat_modifiers.defensive_stages[STAT_STAGE_DEF] < MAX_STAT_STAGE)
break;
if (GetEntInfo(target)->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] < MAX_STAT_STAGE)
break;
if (GetEntInfo(target)->stat_modifiers.defensive_stages[STAT_STAGE_SP_DEF] < MAX_STAT_STAGE)
break;
}
}
if (i == MAX_TEAM_MEMBERS)
return FALSE;
}
break;
case MOVE_MAGNET_RISE:
if (pokemon_info->magnet_rise == TRUE)
return FALSE;
break;
case MOVE_TRICK_ROOM:
if (pokemon_info->speed_stage > 1)
return FALSE;
break;
case MOVE_DEFEND_ORDER:
s32 i;
for (i = 0; i < NUM_STATS_PER_CATEGORY; i++)
{
if (pokemon_info->stat_modifiers.defensive_stages[i] < MAX_STAT_STAGE)
break;
}
if (i == NUM_STATS_PER_CATEGORY)
return FALSE;
break;
case MOVE_METAL_BURST:
if (pokemon_info->reflect_class_status.reflect == STATUS_REFLECT_METAL_BURST)
return FALSE;
break;
case MOVE_NASTY_PLOT:
if (pokemon_info->stat_modifiers.offensive_stages[STAT_STAGE_SP_ATK] == MAX_STAT_STAGE)
return FALSE;
break;
default:
break;
}
return TRUE;
}
#endif
bool8 EntityIsValid__02333FAC(struct entity *entity)
{
if (entity == NULL)
return FALSE;
return entity->type != ENTITY_NOTHING;
}

View File

@ -1,9 +0,0 @@
#include "overlay_29_02333FAC.h"
bool8 EntityIsValid__02333FAC(struct entity *entity)
{
if (entity == NULL)
return FALSE;
return entity->type != ENTITY_NOTHING;
}

View File

@ -112,7 +112,7 @@ void DrawDungeonMenuStatusWindow(struct Window* window)
line_offset = 0;
for (i = 0; i < 4; i++) {
struct entity* party_member = DUNGEON_PTR[0]->party_members[i];
struct entity* party_member = DUNGEON_PTR[0]->monster_slots.party_members[i];
if (party_member == NULL) {
is_valid_member = FALSE;
} else {