From 65c6a9cc73ad4b5dee5d854f4f5bdb272339eda8 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 12 Jul 2025 12:51:14 -0400 Subject: [PATCH 1/3] Fixed some bool types in monster struct --- include/dungeon_mode.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/dungeon_mode.h b/include/dungeon_mode.h index 6b0c4442..4ab95baa 100644 --- a/include/dungeon_mode.h +++ b/include/dungeon_mode.h @@ -328,11 +328,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 From ca431b8de4c9983b45d9ac4de538ce7cd58a6016 Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 12 Jul 2025 13:02:16 -0400 Subject: [PATCH 2/3] Added more decomp.me links --- asm/main_02058F24.s | 2 ++ asm/main_02089694.s | 1 + 2 files changed, 3 insertions(+) diff --git a/asm/main_02058F24.s b/asm/main_02058F24.s index 74135a15..d37900bd 100644 --- a/asm/main_02058F24.s +++ b/asm/main_02058F24.s @@ -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 diff --git a/asm/main_02089694.s b/asm/main_02089694.s index 54d6b185..7e8e0f7f 100644 --- a/asm/main_02089694.s +++ b/asm/main_02089694.s @@ -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} From a6262c870ecb8453aaa3a5e1adf880b2c391de6f Mon Sep 17 00:00:00 2001 From: AnonymousRandomPerson Date: Sat, 12 Jul 2025 17:43:16 -0400 Subject: [PATCH 3/3] Added nonmatching for StatusCheckerCheck --- asm/include/overlay_29_02332A0C.inc | 4 +- asm/overlay_29_02332A0C.s | 3 + include/dungeon.h | 7 +- include/dungeon_mode.h | 11 +- .../{overlay_29_02333FAC.h => move_checks.h} | 7 +- include/tileset.h | 20 + main.lsf | 2 +- src/dungeon_ai_attack.c | 2 +- src/dungeon_ai_itcm.c | 1 + src/move_checks.c | 476 ++++++++++++++++++ src/overlay_29_02333FAC.c | 9 - src/overlay_31_02382820.c | 2 +- 12 files changed, 521 insertions(+), 23 deletions(-) rename include/{overlay_29_02333FAC.h => move_checks.h} (54%) create mode 100644 include/tileset.h create mode 100644 src/move_checks.c delete mode 100644 src/overlay_29_02333FAC.c diff --git a/asm/include/overlay_29_02332A0C.inc b/asm/include/overlay_29_02332A0C.inc index 88c2f67c..5b1d161c 100644 --- a/asm/include/overlay_29_02332A0C.inc +++ b/asm/include/overlay_29_02332A0C.inc @@ -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 diff --git a/asm/overlay_29_02332A0C.s b/asm/overlay_29_02332A0C.s index 069cd9c8..2c00d675 100644 --- a/asm/overlay_29_02332A0C.s +++ b/asm/overlay_29_02332A0C.s @@ -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 diff --git a/include/dungeon.h b/include/dungeon.h index 9b6723c1..e44d04ca 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -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 diff --git a/include/dungeon_mode.h b/include/dungeon_mode.h index 4ab95baa..aa10b211 100644 --- a/include/dungeon_mode.h +++ b/include/dungeon_mode.h @@ -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 diff --git a/include/overlay_29_02333FAC.h b/include/move_checks.h similarity index 54% rename from include/overlay_29_02333FAC.h rename to include/move_checks.h index 052c5fce..e950a5cf 100644 --- a/include/overlay_29_02333FAC.h +++ b/include/move_checks.h @@ -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 diff --git a/include/tileset.h b/include/tileset.h new file mode 100644 index 00000000..f00b826c --- /dev/null +++ b/include/tileset.h @@ -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 \ No newline at end of file diff --git a/main.lsf b/main.lsf index 85f8f1f0..0b39114e 100644 --- a/main.lsf +++ b/main.lsf @@ -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 diff --git a/src/dungeon_ai_attack.c b/src/dungeon_ai_attack.c index 995ae089..13b10bc3 100644 --- a/src/dungeon_ai_attack.c +++ b/src/dungeon_ai_attack.c @@ -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); diff --git a/src/dungeon_ai_itcm.c b/src/dungeon_ai_itcm.c index 2da8cb14..66a32ab7 100644 --- a/src/dungeon_ai_itcm.c +++ b/src/dungeon_ai_itcm.c @@ -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" diff --git a/src/move_checks.c b/src/move_checks.c new file mode 100644 index 00000000..b825fc03 --- /dev/null +++ b/src/move_checks.c @@ -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; +} diff --git a/src/overlay_29_02333FAC.c b/src/overlay_29_02333FAC.c deleted file mode 100644 index af3e2516..00000000 --- a/src/overlay_29_02333FAC.c +++ /dev/null @@ -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; -} diff --git a/src/overlay_31_02382820.c b/src/overlay_31_02382820.c index f8f7d863..f7045952 100644 --- a/src/overlay_31_02382820.c +++ b/src/overlay_31_02382820.c @@ -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 {