mirror of
https://github.com/pret/pmd-sky.git
synced 2026-08-03 01:09:53 -05:00
Merge pull request #145 from AnonymousRandomPerson/main
Added nonmatching for StatusCheckerCheck
This commit is contained in:
commit
ee2e4b4c71
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
20
include/tileset.h
Normal 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
|
||||
2
main.lsf
2
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
476
src/move_checks.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user