diff --git a/asm/include/overlay_29_02301FBC.inc b/asm/include/overlay_29_02301FBC.inc deleted file mode 100644 index e0cc2e49..00000000 --- a/asm/include/overlay_29_02301FBC.inc +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -.public CanLearnIqSkill -.public DisableIqSkill -.public EnableIqSkill -.public GetPerformanceFlagWithChecks -.public GetSpeciesIqSkill -.public IqSkillFlagTest -.public IsMonsterLoneOutlaw -.public MIN_IQ_EXCLUSIVE_MOVE_USER -.public MIN_IQ_ITEM_MASTER diff --git a/asm/include/overlay_29_023021F0.inc b/asm/include/overlay_29_023021F0.inc new file mode 100644 index 00000000..e1dac9cc --- /dev/null +++ b/asm/include/overlay_29_023021F0.inc @@ -0,0 +1,2 @@ +#pragma once +.public UpdateIqSkills diff --git a/asm/overlay_29_02301FBC.s b/asm/overlay_29_02301FBC.s deleted file mode 100644 index c25027ac..00000000 --- a/asm/overlay_29_02301FBC.s +++ /dev/null @@ -1,176 +0,0 @@ - .include "asm/macros.inc" - .include "overlay_29_02301FBC.inc" - - .text - - arm_func_start UpdateIqSkills -UpdateIqSkills: ; 0x02301FBC - stmdb sp!, {r4, r5, r6, lr} - mov r4, r0 - ldrb r0, [r4, #6] - mov r6, #0 - cmp r0, #0 - str r6, [r4, #0x9c] - beq _02302118 - str r6, [r4, #0xa0] - str r6, [r4, #0xa4] - b _0230202C -_02301FE4: - ldrsh r0, [r4, #2] - and r1, r6, #0xff - bl GetSpeciesIqSkill - mov r5, r0 - cmp r5, #0xff - beq _02302034 - ldrsh r0, [r4, #0xe] - mov r1, r5 - bl CanLearnIqSkill - cmp r0, #0 - beq _02302028 - mov r1, r5 - add r0, r4, #0x90 - bl EnableIqSkill - mov r1, r5 - add r0, r4, #0x9c - bl EnableIqSkill -_02302028: - add r6, r6, #1 -_0230202C: - cmp r6, #0x19 - blt _02301FE4 -_02302034: - ldr r0, _023021E8 ; =MIN_IQ_EXCLUSIVE_MOVE_USER - ldrsh r1, [r4, #0xe] - ldrsh r0, [r0] - cmp r1, r0 - bge _02302068 - add r0, r4, #0x9c - mov r1, #0x17 - bl IqSkillFlagTest - cmp r0, #0 - beq _02302068 - add r0, r4, #0x9c - mov r1, #0x17 - bl DisableIqSkill -_02302068: - mov r0, r4 - bl IsMonsterLoneOutlaw - cmp r0, #0 - bne _0230208C - ldr r0, _023021EC ; =MIN_IQ_ITEM_MASTER - ldrsh r1, [r4, #0xe] - ldrsh r0, [r0] - cmp r1, r0 - bge _023020AC -_0230208C: - add r0, r4, #0x9c - mov r1, #0x16 - bl IqSkillFlagTest - cmp r0, #0 - beq _023020AC - add r0, r4, #0x9c - mov r1, #0x16 - bl DisableIqSkill -_023020AC: - add r0, r4, #0x9c - mov r1, #0x15 - bl IqSkillFlagTest - cmp r0, #0 - beq _023020CC - add r0, r4, #0x9c - mov r1, #0x15 - bl DisableIqSkill -_023020CC: - add r0, r4, #0x9c - mov r1, #0x14 - bl IqSkillFlagTest - cmp r0, #0 - beq _023020EC - add r0, r4, #0x9c - mov r1, #0x14 - bl DisableIqSkill -_023020EC: - add r0, r4, #0x9c - mov r1, #0xb - bl IqSkillFlagTest - cmp r0, #0 - beq _0230210C - add r0, r4, #0x9c - mov r1, #0xb - bl DisableIqSkill -_0230210C: - mov r0, #2 - strb r0, [r4, #0xa8] - ldmia sp!, {r4, r5, r6, pc} -_02302118: - str r6, [r4, #0xa0] - str r6, [r4, #0xa4] - b _02302174 -_02302124: - ldrsh r0, [r4, #2] - and r1, r6, #0xff - bl GetSpeciesIqSkill - mov r5, r0 - cmp r5, #0xff - beq _0230217C - ldrsh r0, [r4, #0xe] - mov r1, r5 - bl CanLearnIqSkill - cmp r0, #0 - beq _02302170 - mov r1, r5 - add r0, r4, #0x90 - bl IqSkillFlagTest - cmp r0, #0 - beq _02302170 - mov r1, r5 - add r0, r4, #0x9c - bl EnableIqSkill -_02302170: - add r6, r6, #1 -_02302174: - cmp r6, #0x19 - blt _02302124 -_0230217C: - mov r0, #3 - bl GetPerformanceFlagWithChecks - cmp r0, #0 - beq _023021A4 - add r0, r4, #0x90 - mov r1, #0x18 - bl EnableIqSkill - add r0, r4, #0x9c - mov r1, #0x18 - bl EnableIqSkill -_023021A4: - add r0, r4, #0x90 - mov r1, #0x38 - bl IqSkillFlagTest - cmp r0, #0 - beq _023021C4 - add r0, r4, #0x9c - mov r1, #0x38 - bl EnableIqSkill -_023021C4: - add r0, r4, #0x90 - mov r1, #0x39 - bl IqSkillFlagTest - cmp r0, #0 - ldmeqia sp!, {r4, r5, r6, pc} - add r0, r4, #0x9c - mov r1, #0x39 - bl EnableIqSkill - ldmia sp!, {r4, r5, r6, pc} - .align 2, 0 -_023021E8: .word MIN_IQ_EXCLUSIVE_MOVE_USER -_023021EC: .word MIN_IQ_ITEM_MASTER - arm_func_end UpdateIqSkills - - arm_func_start ov29_023021F0 -ov29_023021F0: ; 0x023021F0 - ldr ip, _023021FC ; =UpdateIqSkills - ldr r0, [r0, #0xb4] - bx ip - .align 2, 0 -_023021FC: .word UpdateIqSkills - arm_func_end ov29_023021F0 diff --git a/asm/overlay_29_023021F0.s b/asm/overlay_29_023021F0.s new file mode 100644 index 00000000..a40cfb72 --- /dev/null +++ b/asm/overlay_29_023021F0.s @@ -0,0 +1,13 @@ + .include "asm/macros.inc" + .include "overlay_29_023021F0.inc" + + .text + + arm_func_start ov29_023021F0 +ov29_023021F0: ; 0x023021F0 + ldr ip, _023021FC ; =UpdateIqSkills + ldr r0, [r0, #0xb4] + bx ip + .align 2, 0 +_023021FC: .word UpdateIqSkills + arm_func_end ov29_023021F0 diff --git a/include/dungeon_pokemon_attributes_1.h b/include/dungeon_pokemon_attributes_1.h index 1ea9965f..5d3308e1 100644 --- a/include/dungeon_pokemon_attributes_1.h +++ b/include/dungeon_pokemon_attributes_1.h @@ -12,5 +12,10 @@ bool8 IsTacticSet(struct entity *entity, enum tactic_id tactic_id); bool8 HasDropeyeStatus(struct entity* entity); // Checks if a monster has a certain IQ skill enabled. bool8 IqSkillIsEnabled(struct entity *entity, enum iq_skill_id iq_skill); +// Updates the IQ skill flags of a monster. +// If the monster is a team member, copies monster::iq_skill_menu_flags to monster::iq_skill_flags. If the monster is an enemy, enables all the IQ skills it can learn (except a few that are only enabled in enemies that have a certain amount of IQ). +// If the monster is an enemy, it also sets its tactic to TACTIC_GO_AFTER_FOES. +// Called after exiting the IQ skills menu or after an enemy spawns. +void UpdateIqSkills(struct monster *monster); #endif //PMDSKY_DUNGEON_POKEMON_ATTRIBUTES_1_H diff --git a/include/enums.h b/include/enums.h index 8fba2114..88d60292 100644 --- a/include/enums.h +++ b/include/enums.h @@ -2,6 +2,7 @@ #define PMDSKY_ENUMS_H #define NUM_TACTICS TACTIC_NONE + 1 +#define MAX_NUM_IQ_SKILLS 25 // Tactic ID. These are usually encoded as bitvectors. enum tactic_id { @@ -2909,6 +2910,7 @@ enum iq_skill_id { IQ_PIERCE_HURLER = 66, IQ_COLLECTOR = 67, IQ_TRUE_POWERIST = 68, + IQ_NONE_2 = 255, }; enum movement_flag @@ -3456,4 +3458,10 @@ enum script_calc_operation { CALC_RANDOM = 11, }; +// https://docs.google.com/spreadsheets/d/1NK3wkC8mOCu-tVkxULLkhpgPR-glApiD2v3zp-mdW7w +enum performance_progress_flag +{ + PERFORMANCE_PROGRESS_FLAG_RANDOM_MISSION = 3 +}; + #endif //PMDSKY_ENUMS_H diff --git a/include/pokemon.h b/include/pokemon.h index c4645583..b4a391eb 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -3,6 +3,6 @@ #include "dungeon_mode.h" -bool8 IqSkillFlagTest(struct iq_skill_flags *iq_skill_flags, u32 iq_id); +bool8 IqSkillFlagTest(u32 *iq_skill_flags, u32 iq_id); #endif //PMDSKY_POKEMON_H diff --git a/main.lsf b/main.lsf index c83bfbc5..a088da30 100644 --- a/main.lsf +++ b/main.lsf @@ -493,7 +493,7 @@ Overlay OVY_29 Object src/dungeon_logic_3.o Object asm/overlay_29_02301E88.o Object src/dungeon_pokemon_attributes_1.o - Object asm/overlay_29_02301FBC.o + Object asm/overlay_29_023021F0.o Object src/dungeon_logic_5.o Object asm/overlay_29_0230231C.o Object src/dungeon_logic_2.o diff --git a/src/dungeon_pokemon_attributes_1.c b/src/dungeon_pokemon_attributes_1.c index dfd84202..9107d648 100644 --- a/src/dungeon_pokemon_attributes_1.c +++ b/src/dungeon_pokemon_attributes_1.c @@ -1,9 +1,19 @@ #include "dungeon_pokemon_attributes_1.h" +#include "dungeon_logic_7.h" #include "dungeon_util_static.h" #include "overlay_29_022FF898.h" #include "overlay_29_023000E4.h" #include "pokemon.h" +extern bool8 CanLearnIqSkill(s32 iq_amount, enum iq_skill_id iq_id); +extern void DisableIqSkill(u32 *iq_skills_flags, enum iq_skill_id iq_id); +extern void EnableIqSkill(u32 *iq_skills_flags, enum iq_skill_id iq_id); +extern bool8 GetPerformanceFlagWithChecks(s32 flag_id); +extern enum iq_skill_id GetSpeciesIqSkill(s16 monster_id, u8 index); + +extern s16 MIN_IQ_EXCLUSIVE_MOVE_USER; +extern s16 MIN_IQ_ITEM_MASTER; + bool8 CanSeeInvisibleMonsters(struct entity *entity) { if (GetEntInfo(entity)->blinker_class_status.blinded == STATUS_BLINKER_EYEDROPS) @@ -38,5 +48,72 @@ bool8 IqSkillIsEnabled(struct entity *entity, enum iq_skill_id iq_skill) if (!entity_info->is_not_team_member && DUNGEON_PTR[0]->iq_disabled) return FALSE; - return IqSkillFlagTest(&entity_info->iq_skill_flags, iq_skill); + return IqSkillFlagTest(entity_info->iq_skill_flags.flags, iq_skill); +} + +void UpdateIqSkills(struct monster *monster) +{ + if (monster->is_not_team_member) + { + monster->iq_skill_flags.flags[0] = 0; + monster->iq_skill_flags.flags[1] = 0; + monster->iq_skill_flags.flags[2] = 0; + + for (s32 i = 0; i < MAX_NUM_IQ_SKILLS; i++) + { + enum iq_skill_id iq_skill = GetSpeciesIqSkill(monster->id, i); + if (iq_skill == IQ_NONE_2) + break; + + if (CanLearnIqSkill(monster->iq, iq_skill)) + { + EnableIqSkill(monster->iq_skill_menu_flags.flags, iq_skill); + EnableIqSkill(monster->iq_skill_flags.flags, iq_skill); + } + } + + if (monster->iq < MIN_IQ_EXCLUSIVE_MOVE_USER && IqSkillFlagTest(monster->iq_skill_flags.flags, IQ_EXCLUSIVE_MOVE_USER)) + DisableIqSkill(monster->iq_skill_flags.flags, IQ_EXCLUSIVE_MOVE_USER); + + if ((IsMonsterLoneOutlaw(monster) || monster->iq < MIN_IQ_ITEM_MASTER) && IqSkillFlagTest(monster->iq_skill_flags.flags, IQ_ITEM_MASTER)) + DisableIqSkill(monster->iq_skill_flags.flags, IQ_ITEM_MASTER); + + if (IqSkillFlagTest(monster->iq_skill_flags.flags, IQ_DEDICATED_TRAVELER)) + DisableIqSkill(monster->iq_skill_flags.flags, IQ_DEDICATED_TRAVELER); + + if (IqSkillFlagTest(monster->iq_skill_flags.flags, IQ_LAVA_EVADER)) + DisableIqSkill(monster->iq_skill_flags.flags, IQ_LAVA_EVADER); + + if (IqSkillFlagTest(monster->iq_skill_flags.flags, IQ_WEAK_TYPE_PICKER)) + DisableIqSkill(monster->iq_skill_flags.flags, IQ_WEAK_TYPE_PICKER); + + monster->tactic = TACTIC_GO_AFTER_FOES; + } + else + { + monster->iq_skill_flags.flags[0] = 0; + monster->iq_skill_flags.flags[1] = 0; + monster->iq_skill_flags.flags[2] = 0; + for (s32 i = 0; i < MAX_NUM_IQ_SKILLS; i++) + { + enum iq_skill_id iq_skill = GetSpeciesIqSkill(monster->id, i); + if (iq_skill == IQ_NONE_2) + break; + + if (CanLearnIqSkill(monster->iq, iq_skill) && IqSkillFlagTest(monster->iq_skill_menu_flags.flags, iq_skill)) + EnableIqSkill(monster->iq_skill_flags.flags, iq_skill); + } + + if (GetPerformanceFlagWithChecks(PERFORMANCE_PROGRESS_FLAG_RANDOM_MISSION)) + { + EnableIqSkill(monster->iq_skill_menu_flags.flags, IQ_ESCAPIST); + EnableIqSkill(monster->iq_skill_flags.flags, IQ_ESCAPIST); + } + + if (IqSkillFlagTest(monster->iq_skill_menu_flags.flags, IQ_BRICK_TOUGH)) + EnableIqSkill(monster->iq_skill_flags.flags, IQ_BRICK_TOUGH); + + if (IqSkillFlagTest(monster->iq_skill_menu_flags.flags, IQ_MULTITALENT)) + EnableIqSkill(monster->iq_skill_flags.flags, IQ_MULTITALENT); + } } diff --git a/src/pokemon.c b/src/pokemon.c index 9dc61f43..2580ec01 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1,9 +1,9 @@ #include "pokemon.h" -bool8 IqSkillFlagTest(struct iq_skill_flags *iq_skill_flags, u32 iq_id) +bool8 IqSkillFlagTest(u32 *iq_skill_flags, u32 iq_id) { u32 flags_index = iq_id >> 5; - u32 flags_section = iq_skill_flags->flags[flags_index]; + u32 flags_section = iq_skill_flags[flags_index]; u32 flag_bit_index = iq_id - (flags_index << 5); return (flags_section & (1 << flag_bit_index)) != 0; }