diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 5e08c7cdb5..ffa1176890 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1632,7 +1632,11 @@ .macro trygulpmissile callnative BS_TryGulpMissile .endm - + + .macro tryactivategulpmissile + callnative BS_TryActivateGulpMissile + .endm + .macro tryquash failInstr:req callnative BS_TryQuash .4byte \failInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 26beaf139a..231788d3d3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -84,6 +84,7 @@ BattleScript_EffectShedTail:: jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed setsubstitute jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString + orword gHitMarker, HITMARKER_PASSIVE_DAMAGE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -108,7 +109,7 @@ BattleScript_EffectFilletAway:: jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ButItFailed BattleScript_FilletAwayTryAttack:: halvehp BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE attackanimation waitanimation setbyte sSTAT_ANIM_PLAYED, FALSE @@ -1715,6 +1716,8 @@ BattleScript_EffectCopycat:: trycopycat BattleScript_CopycatFail attackanimation waitanimation + setbyte sB_ANIM_TURN, 0 + setbyte sB_ANIM_TARGETS_HIT, 0 jumptocalledmove TRUE BattleScript_CopycatFail: ppreduce @@ -3866,6 +3869,7 @@ BattleScript_EffectSubstitute:: jumpifstatus2 BS_ATTACKER, STATUS2_SUBSTITUTE, BattleScript_AlreadyHasSubstitute setsubstitute jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString + orword gHitMarker, HITMARKER_PASSIVE_DAMAGE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -4600,7 +4604,7 @@ BattleScript_EffectBellyDrum:: ppreduce jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed halvehp BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -5490,6 +5494,7 @@ BattleScript_EffectCamouflage:: BattleScript_FaintAttacker:: tryillusionoff BS_ATTACKER + tryactivategulpmissile playfaintcry BS_ATTACKER pause B_WAIT_TIME_LONG dofaintanimation BS_ATTACKER @@ -5502,6 +5507,7 @@ BattleScript_FaintAttacker:: BattleScript_FaintTarget:: tryillusionoff BS_TARGET + tryactivategulpmissile playfaintcry BS_TARGET pause B_WAIT_TIME_LONG dofaintanimation BS_TARGET diff --git a/graphics/pokemon/unown/anim_front.png b/graphics/pokemon/unown/anim_front.png deleted file mode 100644 index 065d82a47f..0000000000 Binary files a/graphics/pokemon/unown/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/b/anim_front.png b/graphics/pokemon/unown/b/anim_front.png deleted file mode 100644 index bedc986348..0000000000 Binary files a/graphics/pokemon/unown/b/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/b/front.png b/graphics/pokemon/unown/b/front.png new file mode 100644 index 0000000000..427eae3e06 Binary files /dev/null and b/graphics/pokemon/unown/b/front.png differ diff --git a/graphics/pokemon/unown/c/anim_front.png b/graphics/pokemon/unown/c/anim_front.png deleted file mode 100644 index 6699bbbb5b..0000000000 Binary files a/graphics/pokemon/unown/c/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/c/front.png b/graphics/pokemon/unown/c/front.png new file mode 100644 index 0000000000..8ae43e1fda Binary files /dev/null and b/graphics/pokemon/unown/c/front.png differ diff --git a/graphics/pokemon/unown/d/anim_front.png b/graphics/pokemon/unown/d/anim_front.png deleted file mode 100644 index 7491a13fbb..0000000000 Binary files a/graphics/pokemon/unown/d/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/d/front.png b/graphics/pokemon/unown/d/front.png new file mode 100644 index 0000000000..b4e6521a8d Binary files /dev/null and b/graphics/pokemon/unown/d/front.png differ diff --git a/graphics/pokemon/unown/e/anim_front.png b/graphics/pokemon/unown/e/anim_front.png deleted file mode 100644 index a761cdd95a..0000000000 Binary files a/graphics/pokemon/unown/e/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/e/front.png b/graphics/pokemon/unown/e/front.png new file mode 100644 index 0000000000..78bba27771 Binary files /dev/null and b/graphics/pokemon/unown/e/front.png differ diff --git a/graphics/pokemon/unown/exclamation_mark/anim_front.png b/graphics/pokemon/unown/exclamation_mark/anim_front.png deleted file mode 100644 index 96c436e8c8..0000000000 Binary files a/graphics/pokemon/unown/exclamation_mark/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/exclamation_mark/front.png b/graphics/pokemon/unown/exclamation_mark/front.png new file mode 100644 index 0000000000..5e82b5a015 Binary files /dev/null and b/graphics/pokemon/unown/exclamation_mark/front.png differ diff --git a/graphics/pokemon/unown/f/anim_front.png b/graphics/pokemon/unown/f/anim_front.png deleted file mode 100644 index 1c96856592..0000000000 Binary files a/graphics/pokemon/unown/f/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/f/front.png b/graphics/pokemon/unown/f/front.png new file mode 100644 index 0000000000..cc483687ad Binary files /dev/null and b/graphics/pokemon/unown/f/front.png differ diff --git a/graphics/pokemon/unown/front.png b/graphics/pokemon/unown/front.png new file mode 100644 index 0000000000..e47b643588 Binary files /dev/null and b/graphics/pokemon/unown/front.png differ diff --git a/graphics/pokemon/unown/g/anim_front.png b/graphics/pokemon/unown/g/anim_front.png deleted file mode 100644 index 028bd4cadd..0000000000 Binary files a/graphics/pokemon/unown/g/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/g/front.png b/graphics/pokemon/unown/g/front.png new file mode 100644 index 0000000000..a56bfc82b4 Binary files /dev/null and b/graphics/pokemon/unown/g/front.png differ diff --git a/graphics/pokemon/unown/h/anim_front.png b/graphics/pokemon/unown/h/anim_front.png deleted file mode 100644 index 686e70d4bc..0000000000 Binary files a/graphics/pokemon/unown/h/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/h/front.png b/graphics/pokemon/unown/h/front.png new file mode 100644 index 0000000000..7ead734a09 Binary files /dev/null and b/graphics/pokemon/unown/h/front.png differ diff --git a/graphics/pokemon/unown/i/anim_front.png b/graphics/pokemon/unown/i/anim_front.png deleted file mode 100644 index 04a748fa0d..0000000000 Binary files a/graphics/pokemon/unown/i/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/i/front.png b/graphics/pokemon/unown/i/front.png new file mode 100644 index 0000000000..4cab90a33b Binary files /dev/null and b/graphics/pokemon/unown/i/front.png differ diff --git a/graphics/pokemon/unown/j/anim_front.png b/graphics/pokemon/unown/j/anim_front.png deleted file mode 100644 index e2906d253a..0000000000 Binary files a/graphics/pokemon/unown/j/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/j/front.png b/graphics/pokemon/unown/j/front.png new file mode 100644 index 0000000000..f91eabc61f Binary files /dev/null and b/graphics/pokemon/unown/j/front.png differ diff --git a/graphics/pokemon/unown/k/anim_front.png b/graphics/pokemon/unown/k/anim_front.png deleted file mode 100644 index b83ef195f4..0000000000 Binary files a/graphics/pokemon/unown/k/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/k/front.png b/graphics/pokemon/unown/k/front.png new file mode 100644 index 0000000000..23e68bc5f6 Binary files /dev/null and b/graphics/pokemon/unown/k/front.png differ diff --git a/graphics/pokemon/unown/l/anim_front.png b/graphics/pokemon/unown/l/anim_front.png deleted file mode 100644 index 9d8b23af4d..0000000000 Binary files a/graphics/pokemon/unown/l/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/l/front.png b/graphics/pokemon/unown/l/front.png new file mode 100644 index 0000000000..1892c9bbfc Binary files /dev/null and b/graphics/pokemon/unown/l/front.png differ diff --git a/graphics/pokemon/unown/m/anim_front.png b/graphics/pokemon/unown/m/anim_front.png deleted file mode 100644 index ee9c7c7a83..0000000000 Binary files a/graphics/pokemon/unown/m/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/m/front.png b/graphics/pokemon/unown/m/front.png new file mode 100644 index 0000000000..9fb350aca5 Binary files /dev/null and b/graphics/pokemon/unown/m/front.png differ diff --git a/graphics/pokemon/unown/n/anim_front.png b/graphics/pokemon/unown/n/anim_front.png deleted file mode 100644 index 47cac4516b..0000000000 Binary files a/graphics/pokemon/unown/n/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/n/front.png b/graphics/pokemon/unown/n/front.png new file mode 100644 index 0000000000..92ce38f922 Binary files /dev/null and b/graphics/pokemon/unown/n/front.png differ diff --git a/graphics/pokemon/unown/o/anim_front.png b/graphics/pokemon/unown/o/anim_front.png deleted file mode 100644 index b32cdb3250..0000000000 Binary files a/graphics/pokemon/unown/o/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/o/front.png b/graphics/pokemon/unown/o/front.png new file mode 100644 index 0000000000..979e7ca0bf Binary files /dev/null and b/graphics/pokemon/unown/o/front.png differ diff --git a/graphics/pokemon/unown/p/anim_front.png b/graphics/pokemon/unown/p/anim_front.png deleted file mode 100644 index 01aa0329c7..0000000000 Binary files a/graphics/pokemon/unown/p/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/p/front.png b/graphics/pokemon/unown/p/front.png new file mode 100644 index 0000000000..2f0820946f Binary files /dev/null and b/graphics/pokemon/unown/p/front.png differ diff --git a/graphics/pokemon/unown/q/anim_front.png b/graphics/pokemon/unown/q/anim_front.png deleted file mode 100644 index 18c930e696..0000000000 Binary files a/graphics/pokemon/unown/q/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/q/front.png b/graphics/pokemon/unown/q/front.png new file mode 100644 index 0000000000..bd3d52ec21 Binary files /dev/null and b/graphics/pokemon/unown/q/front.png differ diff --git a/graphics/pokemon/unown/question_mark/anim_front.png b/graphics/pokemon/unown/question_mark/anim_front.png deleted file mode 100644 index 8a2f8bb6ca..0000000000 Binary files a/graphics/pokemon/unown/question_mark/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/question_mark/front.png b/graphics/pokemon/unown/question_mark/front.png new file mode 100644 index 0000000000..3553f02446 Binary files /dev/null and b/graphics/pokemon/unown/question_mark/front.png differ diff --git a/graphics/pokemon/unown/r/anim_front.png b/graphics/pokemon/unown/r/anim_front.png deleted file mode 100644 index 0b861d277e..0000000000 Binary files a/graphics/pokemon/unown/r/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/r/front.png b/graphics/pokemon/unown/r/front.png new file mode 100644 index 0000000000..9f47658bb8 Binary files /dev/null and b/graphics/pokemon/unown/r/front.png differ diff --git a/graphics/pokemon/unown/s/anim_front.png b/graphics/pokemon/unown/s/anim_front.png deleted file mode 100644 index 17016ac1ca..0000000000 Binary files a/graphics/pokemon/unown/s/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/s/front.png b/graphics/pokemon/unown/s/front.png new file mode 100644 index 0000000000..a231c38b3d Binary files /dev/null and b/graphics/pokemon/unown/s/front.png differ diff --git a/graphics/pokemon/unown/t/anim_front.png b/graphics/pokemon/unown/t/anim_front.png deleted file mode 100644 index 556ab78ce8..0000000000 Binary files a/graphics/pokemon/unown/t/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/t/front.png b/graphics/pokemon/unown/t/front.png new file mode 100644 index 0000000000..ed02d17e1e Binary files /dev/null and b/graphics/pokemon/unown/t/front.png differ diff --git a/graphics/pokemon/unown/u/anim_front.png b/graphics/pokemon/unown/u/anim_front.png deleted file mode 100644 index cea47fd5be..0000000000 Binary files a/graphics/pokemon/unown/u/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/u/front.png b/graphics/pokemon/unown/u/front.png new file mode 100644 index 0000000000..43631f3354 Binary files /dev/null and b/graphics/pokemon/unown/u/front.png differ diff --git a/graphics/pokemon/unown/v/anim_front.png b/graphics/pokemon/unown/v/anim_front.png deleted file mode 100644 index d073949e54..0000000000 Binary files a/graphics/pokemon/unown/v/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/v/front.png b/graphics/pokemon/unown/v/front.png new file mode 100644 index 0000000000..af578b4fa9 Binary files /dev/null and b/graphics/pokemon/unown/v/front.png differ diff --git a/graphics/pokemon/unown/w/anim_front.png b/graphics/pokemon/unown/w/anim_front.png deleted file mode 100644 index d34a16f059..0000000000 Binary files a/graphics/pokemon/unown/w/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/w/front.png b/graphics/pokemon/unown/w/front.png new file mode 100644 index 0000000000..dd9f9d00f7 Binary files /dev/null and b/graphics/pokemon/unown/w/front.png differ diff --git a/graphics/pokemon/unown/x/anim_front.png b/graphics/pokemon/unown/x/anim_front.png deleted file mode 100644 index a75ab916c2..0000000000 Binary files a/graphics/pokemon/unown/x/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/x/front.png b/graphics/pokemon/unown/x/front.png new file mode 100644 index 0000000000..d591825d06 Binary files /dev/null and b/graphics/pokemon/unown/x/front.png differ diff --git a/graphics/pokemon/unown/y/anim_front.png b/graphics/pokemon/unown/y/anim_front.png deleted file mode 100644 index 8b5221943f..0000000000 Binary files a/graphics/pokemon/unown/y/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/y/front.png b/graphics/pokemon/unown/y/front.png new file mode 100644 index 0000000000..41bfa3859a Binary files /dev/null and b/graphics/pokemon/unown/y/front.png differ diff --git a/graphics/pokemon/unown/z/anim_front.png b/graphics/pokemon/unown/z/anim_front.png deleted file mode 100644 index 3080f7347c..0000000000 Binary files a/graphics/pokemon/unown/z/anim_front.png and /dev/null differ diff --git a/graphics/pokemon/unown/z/front.png b/graphics/pokemon/unown/z/front.png new file mode 100644 index 0000000000..c1dd680070 Binary files /dev/null and b/graphics/pokemon/unown/z/front.png differ diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index 18148a89b0..e2c7804091 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -32,13 +32,13 @@ #define BEST_DAMAGE_MOVE 1 // Move with the most amount of hits with the best accuracy/effect #define POWERFUL_STATUS_MOVE 10 // Moves with this score will be chosen over a move that faints target -// Temporary scores that are added together to determine a final score at the at of AI_CalcMoveScore +// Temporary scores that are added together to determine a final score at the at of AI_CalcMoveEffectScore #define WEAK_EFFECT 1 #define DECENT_EFFECT 2 #define GOOD_EFFECT 4 #define BEST_EFFECT 6 -// AI_CalcMoveScore final score +// AI_CalcMoveEffectScore final score #define NOT_GOOD_ENOUGH 0 // Not worth using over a damaging move #define GOOD_MOVE_EFFECTS 2 // Worth using over a damaging move #define PREFERRED_MOVE_EFFECTS 3 // Worth using over a damagin move and is better then DECENT_EFFECT diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index ac7aea429b..bd2b8fb920 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -179,6 +179,7 @@ bool32 SideHasMoveCategory(u32 battlerId, u32 category); // score increases void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score); +void IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score); void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index d23dc0d2bd..d94cc90a37 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -120,4 +120,7 @@ // param1: status #define FORM_CHANGE_STATUS 20 +// Form change that activates after move is used. Currently only used for activating Gulp Missile. +#define FORM_CHANGE_HIT_BY_MOVE 21 + #endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index da8b3764a3..de4c683c67 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -838,7 +838,22 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case AI_EFFECTIVENESS_x0_125: case AI_EFFECTIVENESS_x0_25: - RETURN_SCORE_MINUS(10); + switch (moveEffect) + { + case EFFECT_FIXED_DAMAGE_ARG: + case EFFECT_LEVEL_DAMAGE: + case EFFECT_PSYWAVE: + case EFFECT_OHKO: + case EFFECT_BIDE: + case EFFECT_SUPER_FANG: + case EFFECT_ENDEAVOR: + case EFFECT_COUNTER: + case EFFECT_MIRROR_COAT: + case EFFECT_METAL_BURST: + break; + default: + RETURN_SCORE_MINUS(10); + } break; } @@ -3162,7 +3177,7 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) return score; } -static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) +static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { // move data u32 moveEffect = gMovesInfo[move].effect; @@ -3593,7 +3608,7 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) else ADJUST_SCORE(WEAK_EFFECT); } - else if (aiData->abilities[battlerAtk] != ABILITY_CONTRARY) + else { IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF, &score); @@ -4408,56 +4423,88 @@ static u32 AI_CalcMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) // Consider move effects that target self if (gMovesInfo[move].additionalEffects[i].self) { - u32 oneStageStatId = STAT_CHANGE_ATK + gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_1; - u32 twoStageStatId = STAT_CHANGE_ATK_2 + gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_1; + u32 StageStatId; - switch (gMovesInfo[move].additionalEffects[i].moveEffect) + if (aiData->abilities[battlerAtk] != ABILITY_CONTRARY) { - case MOVE_EFFECT_SPD_PLUS_2: - case MOVE_EFFECT_SPD_PLUS_1: - if (aiData->abilities[battlerAtk] != ABILITY_CONTRARY && !AI_STRIKES_FIRST(battlerAtk, battlerDef, move)) - ADJUST_SCORE(GOOD_EFFECT); - break; + switch (gMovesInfo[move].additionalEffects[i].moveEffect) + { case MOVE_EFFECT_ATK_PLUS_1: case MOVE_EFFECT_DEF_PLUS_1: + case MOVE_EFFECT_SPD_PLUS_1: case MOVE_EFFECT_SP_ATK_PLUS_1: case MOVE_EFFECT_SP_DEF_PLUS_1: - case MOVE_EFFECT_ACC_PLUS_1: - case MOVE_EFFECT_EVS_PLUS_1: - IncreaseStatUpScore(battlerAtk, battlerDef, oneStageStatId, &score); + StageStatId = STAT_CHANGE_ATK + gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_1; + IncreaseStatUpScore(battlerAtk, battlerDef, StageStatId, &score); break; case MOVE_EFFECT_ATK_PLUS_2: case MOVE_EFFECT_DEF_PLUS_2: + case MOVE_EFFECT_SPD_PLUS_2: case MOVE_EFFECT_SP_ATK_PLUS_2: case MOVE_EFFECT_SP_DEF_PLUS_2: - case MOVE_EFFECT_ACC_PLUS_2: - case MOVE_EFFECT_EVS_PLUS_2: - IncreaseStatUpScore(battlerAtk, battlerDef, twoStageStatId, &score); + StageStatId = STAT_CHANGE_ATK_2 + gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_1; + IncreaseStatUpScore(battlerAtk, battlerDef, StageStatId, &score); break; - // Effects that lower stat(s) - only need to consider Contrary - case MOVE_EFFECT_ATK_MINUS_1: - case MOVE_EFFECT_DEF_MINUS_1: - case MOVE_EFFECT_SPD_MINUS_1: - case MOVE_EFFECT_SP_ATK_MINUS_1: - case MOVE_EFFECT_SP_DEF_MINUS_1: - case MOVE_EFFECT_DEF_SPDEF_DOWN: - case MOVE_EFFECT_ATK_DEF_DOWN: - case MOVE_EFFECT_SP_ATK_TWO_DOWN: - if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) - IncreaseStatUpScore(battlerAtk, battlerDef, oneStageStatId, &score); - case MOVE_EFFECT_V_CREATE: - if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) - { - IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF, &score); - IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED, &score); - IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF, &score); - } + case MOVE_EFFECT_ACC_PLUS_1: + case MOVE_EFFECT_ACC_PLUS_2: + IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ACC, &score); + break; + case MOVE_EFFECT_EVS_PLUS_1: + case MOVE_EFFECT_EVS_PLUS_2: + IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_EVASION, &score); break; case MOVE_EFFECT_RAPID_SPIN: if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED)) ADJUST_SCORE(GOOD_EFFECT); break; + } + } + else + { + switch (gMovesInfo[move].additionalEffects[i].moveEffect) + { + case MOVE_EFFECT_ATK_MINUS_1: + case MOVE_EFFECT_DEF_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SP_ATK_MINUS_1: + case MOVE_EFFECT_SP_DEF_MINUS_1: + StageStatId = STAT_CHANGE_ATK + gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_MINUS_1; + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, StageStatId, &score); + break; + case MOVE_EFFECT_ATK_MINUS_2: + case MOVE_EFFECT_DEF_MINUS_2: + case MOVE_EFFECT_SPD_MINUS_2: + case MOVE_EFFECT_SP_ATK_MINUS_2: + case MOVE_EFFECT_SP_DEF_MINUS_2: + StageStatId = STAT_CHANGE_ATK + gMovesInfo[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_MINUS_2; + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, StageStatId, &score); + break; + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_2: + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_ACC, &score); + break; + case MOVE_EFFECT_EVS_MINUS_1: + case MOVE_EFFECT_EVS_MINUS_2: + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_EVASION, &score); + break; + case MOVE_EFFECT_DEF_SPDEF_DOWN: + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_DEF, &score); + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPDEF, &score); + break; + case MOVE_EFFECT_ATK_DEF_DOWN: + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_ATK, &score); + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_DEF, &score); + break; + case MOVE_EFFECT_SP_ATK_TWO_DOWN: + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2, &score); + break; + case MOVE_EFFECT_V_CREATE: + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_DEF, &score); + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPEED, &score); + IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPDEF, &score); + break; + } } } else // consider move effects that hinder the target @@ -4640,8 +4687,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score score += AI_CompareDamagingMoves(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex); } - // Calculates score based on effects of a move - score += AI_CalcMoveScore(battlerAtk, battlerDef, move); + score += AI_CalcMoveEffectScore(battlerAtk, battlerDef, move); return score; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 18dd3fc0c7..de6775ea59 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -431,6 +431,7 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) return TRUE; break; case EFFECT_LOW_KICK: + case EFFECT_HEAT_CRASH: if (IsDynamaxed(battlerDef)) return TRUE; break; @@ -644,22 +645,35 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 switch (gMovesInfo[move].additionalEffects[i].moveEffect) { case MOVE_EFFECT_ATK_PLUS_1: + case MOVE_EFFECT_ATK_PLUS_2: if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) return TRUE; break; - case MOVE_EFFECT_DEF_PLUS_2: case MOVE_EFFECT_DEF_PLUS_1: + case MOVE_EFFECT_DEF_PLUS_2: if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF)) return TRUE; break; case MOVE_EFFECT_SPD_PLUS_1: + case MOVE_EFFECT_SPD_PLUS_2: if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPEED)) return TRUE; break; case MOVE_EFFECT_SP_ATK_PLUS_1: + case MOVE_EFFECT_SP_ATK_PLUS_2: if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPATK)) return TRUE; break; + case MOVE_EFFECT_EVS_PLUS_1: + case MOVE_EFFECT_EVS_PLUS_2: + if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_EVASION)) + return TRUE; + break; + case MOVE_EFFECT_ACC_PLUS_1: + case MOVE_EFFECT_ACC_PLUS_2: + if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ACC)) + return TRUE; + break; case MOVE_EFFECT_ALL_STATS_UP: for (i = STAT_ATK; i <= NUM_STATS; i++) { @@ -754,18 +768,45 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s case MOVE_EFFECT_DEF_MINUS_1: case MOVE_EFFECT_SPD_MINUS_1: case MOVE_EFFECT_SP_ATK_MINUS_1: + case MOVE_EFFECT_SP_DEF_MINUS_1: + case MOVE_EFFECT_EVS_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_ATK_MINUS_2: + case MOVE_EFFECT_DEF_MINUS_2: + case MOVE_EFFECT_SPD_MINUS_2: + case MOVE_EFFECT_SP_ATK_MINUS_2: + case MOVE_EFFECT_SP_DEF_MINUS_2: + case MOVE_EFFECT_EVS_MINUS_2: + case MOVE_EFFECT_ACC_MINUS_2: case MOVE_EFFECT_SP_ATK_TWO_DOWN: case MOVE_EFFECT_V_CREATE: case MOVE_EFFECT_ATK_DEF_DOWN: case MOVE_EFFECT_DEF_SPDEF_DOWN: - case MOVE_EFFECT_SP_DEF_MINUS_1: - case MOVE_EFFECT_SP_DEF_MINUS_2: - if ((gMovesInfo[move].additionalEffects[i].self && GetBattlerAbility(battlerAtk) != ABILITY_CONTRARY) - || (noOfHitsToKo != 1 && abilityDef == ABILITY_CONTRARY && !IsMoldBreakerTypeAbility(abilityAtk))) + if ((gMovesInfo[move].additionalEffects[i].self && abilityAtk != ABILITY_CONTRARY) + || (noOfHitsToKo != 1 && abilityDef == ABILITY_CONTRARY && !DoesBattlerIgnoreAbilityChecks(abilityAtk, move))) return TRUE; break; case MOVE_EFFECT_RECHARGE: return gMovesInfo[move].additionalEffects[i].self; + case MOVE_EFFECT_ATK_PLUS_1: + case MOVE_EFFECT_DEF_PLUS_1: + case MOVE_EFFECT_SPD_PLUS_1: + case MOVE_EFFECT_SP_ATK_PLUS_1: + case MOVE_EFFECT_SP_DEF_PLUS_1: + case MOVE_EFFECT_EVS_PLUS_1: + case MOVE_EFFECT_ACC_PLUS_1: + case MOVE_EFFECT_ATK_PLUS_2: + case MOVE_EFFECT_DEF_PLUS_2: + case MOVE_EFFECT_SPD_PLUS_2: + case MOVE_EFFECT_SP_ATK_PLUS_2: + case MOVE_EFFECT_SP_DEF_PLUS_2: + case MOVE_EFFECT_EVS_PLUS_2: + case MOVE_EFFECT_ACC_PLUS_2: + case MOVE_EFFECT_ALL_STATS_UP: + if ((gMovesInfo[move].additionalEffects[i].self && abilityAtk == ABILITY_CONTRARY) + || (noOfHitsToKo != 1 && !(abilityDef == ABILITY_CONTRARY && !DoesBattlerIgnoreAbilityChecks(abilityAtk, move)))) + return TRUE; + break; } } break; @@ -3405,13 +3446,13 @@ bool32 IsRecycleEncouragedItem(u32 item) return FALSE; } -void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score) +static void IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score, bool32 considerContrary) { u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk); u32 aiIsFaster = GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == AI_IS_FASTER; u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); - if (AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY) + if (considerContrary && AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY) return; // Don't increase stat if AI is at +4 @@ -3505,6 +3546,16 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score) } } +void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score) +{ + IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, score, TRUE); +} + +void IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score) +{ + IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, score, FALSE); +} + void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) { if (((AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 8cc5afb424..6f6ef8a9d6 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -899,8 +899,8 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo { if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality) { - personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); + personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_PERSONALITY); + isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_IS_SHINY); } else { @@ -917,8 +917,8 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo { if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality) { - personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); + personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_PERSONALITY); + isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_IS_SHINY); } else { diff --git a/src/battle_main.c b/src/battle_main.c index 7f6f123357..6e67d831c8 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3290,11 +3290,13 @@ static void ClearSetBScriptingStruct(void) { // windowsType is set up earlier in BattleInitBgsAndWindows, so we need to save the value u32 temp = gBattleScripting.windowsType; + u32 specialBattleType = gBattleScripting.specialTrainerBattleType; memset(&gBattleScripting, 0, sizeof(gBattleScripting)); gBattleScripting.windowsType = temp; gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle; gBattleScripting.expOnCatch = (B_EXP_CATCH >= GEN_6); + gBattleScripting.specialTrainerBattleType = specialBattleType; } static void BattleStartClearSetData(void) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7e46edcfc5..4f04d0a425 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3162,7 +3162,6 @@ void SetMoveEffect(bool32 primary, bool32 certain) } else { - u8 side; switch (gBattleScripting.moveEffect) { case MOVE_EFFECT_CONFUSION: @@ -3176,7 +3175,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) // If the confusion is activating due to being released from Sky Drop, go to "confused due to fatigue" script. // Otherwise, do normal confusion script. - if(gCurrentMove == MOVE_SKY_DROP) + if (gCurrentMove == MOVE_SKY_DROP) { gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE); gBattlerAttacker = gEffectBattler; @@ -3420,35 +3419,13 @@ void SetMoveEffect(bool32 primary, bool32 certain) break; case MOVE_EFFECT_STEAL_ITEM: { - if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)) - { - gBattlescriptCurrInstr++; - break; - } - - side = GetBattlerSide(gBattlerAttacker); - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT - && !(gBattleTypeFlags & - (BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_LINK - | BATTLE_TYPE_RECORDED_LINK - | BATTLE_TYPE_SECRET_BASE))) + if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) + || gBattleMons[gBattlerAttacker].item != ITEM_NONE + || gBattleMons[gBattlerTarget].item == ITEM_NONE) { gBattlescriptCurrInstr++; } - else if (!(gBattleTypeFlags & - (BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_LINK - | BATTLE_TYPE_RECORDED_LINK - | BATTLE_TYPE_SECRET_BASE)) - && (gWishFutureKnock.knockedOffMons[side] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]])) - { - gBattlescriptCurrInstr++; - } - else if (gBattleMons[gBattlerTarget].item - && GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) + else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_NoItemSteal; @@ -3456,12 +3433,6 @@ void SetMoveEffect(bool32 primary, bool32 certain) gLastUsedAbility = gBattleMons[gBattlerTarget].ability; RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } - else if (gBattleMons[gBattlerAttacker].item != ITEM_NONE - || gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY_E_READER - || gBattleMons[gBattlerTarget].item == ITEM_NONE) - { - gBattlescriptCurrInstr++; - } else { StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item @@ -4438,15 +4409,19 @@ static void Cmd_getexp(void) gBattleMoveDamage += GetSoftLevelCapExpValue(gPlayerParty[*expMonId].level, gBattleStruct->expShareExpValue);; } - if (EXP_CAP_HARD && gBattleMoveDamage != 0) + ApplyExperienceMultipliers(&gBattleMoveDamage, *expMonId, gBattlerFainted); + + if (B_EXP_CAP_TYPE == EXP_CAP_HARD && gBattleMoveDamage != 0) { u32 growthRate = gSpeciesInfo[GetMonData(&gPlayerParty[*expMonId], MON_DATA_SPECIES)].growthRate; - if (gExperienceTables[growthRate][GetCurrentLevelCap()] < gExperienceTables[growthRate][GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL)] + gBattleMoveDamage) - gBattleMoveDamage = gExperienceTables[growthRate][GetCurrentLevelCap()]; - } + u32 currentExp = GetMonData(&gPlayerParty[*expMonId], MON_DATA_EXP); + u32 levelCap = GetCurrentLevelCap(); - if (!EXP_CAP_HARD || gBattleMoveDamage != 0) // Edge case for hard level caps. Prevents mons from getting 1 exp - ApplyExperienceMultipliers(&gBattleMoveDamage, *expMonId, gBattlerFainted); + if (GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL) >= levelCap) + gBattleMoveDamage = 0; + else if (gExperienceTables[growthRate][levelCap] < currentExp + gBattleMoveDamage) + gBattleMoveDamage = gExperienceTables[growthRate][levelCap] - currentExp; + } if (IsTradedMon(&gPlayerParty[*expMonId])) { @@ -16712,7 +16687,7 @@ void BS_TryCopycat(void) { NATIVE_ARGS(const u8 *failInstr); - if (gLastUsedMove == MOVE_NONE || gLastUsedMove == MOVE_UNAVAILABLE || gMovesInfo[gLastUsedMove].copycatBanned) + if (gLastUsedMove == MOVE_NONE || gLastUsedMove == MOVE_UNAVAILABLE || gMovesInfo[gLastUsedMove].copycatBanned || IsZMove(gLastUsedMove)) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -16919,6 +16894,40 @@ void BS_TryGulpMissile(void) gBattlescriptCurrInstr = cmd->nextInstr; } +void BS_TryActivateGulpMissile(void) +{ + NATIVE_ARGS(); + + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && !gProtectStructs[gBattlerAttacker].confusionSelfDmg + && TARGET_TURN_DAMAGED + && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT + && GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE) + { + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + + switch(gBattleMons[gBattlerTarget].species) + { + case SPECIES_CRAMORANT_GORGING: + BattleScriptPushCursor(); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); + gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; + return; + case SPECIES_CRAMORANT_GULPING: + BattleScriptPushCursor(); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); + gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; + return; + } + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_TryQuash(void) { NATIVE_ARGS(const u8 *failInstr); diff --git a/src/battle_util.c b/src/battle_util.c index 358aa75e39..aa4f405d84 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3002,6 +3002,15 @@ bool32 HandleWishPerishSongOnTurnEnd(void) { struct Pokemon *party; + if (gWishFutureKnock.futureSightCounter[battler] == 0 + && gWishFutureKnock.futureSightCounter[BATTLE_PARTNER(battler)] == 0) + { + gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_FUTUREATTACK; + } + + if (!IsBattlerAlive(battler)) + continue; + if (gWishFutureKnock.futureSightMove[battler] == MOVE_FUTURE_SIGHT) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; else @@ -3020,12 +3029,6 @@ bool32 HandleWishPerishSongOnTurnEnd(void) BattleScriptExecute(BattleScript_MonTookFutureAttack); - if (gWishFutureKnock.futureSightCounter[battler] == 0 - && gWishFutureKnock.futureSightCounter[BATTLE_PARTNER(battler)] == 0) - { - gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_FUTUREATTACK; - } - return TRUE; } } @@ -5646,34 +5649,30 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && IsBattlerAlive(battler)) + && IsBattlerAlive(battler) + && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT) { - // TODO: Convert this to a proper FORM_CHANGE type. - if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { - gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - } - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; - effect++; + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; } - else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) + + switch(gBattleMons[gBattlerTarget].species) { - gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - } - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; - effect++; + case SPECIES_CRAMORANT_GORGING: + TryBattleFormChange(battler, FORM_CHANGE_HIT_BY_MOVE); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; + effect++; + break; + case SPECIES_CRAMORANT_GULPING: + TryBattleFormChange(battler, FORM_CHANGE_HIT_BY_MOVE); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; + effect++; + break; } } break; @@ -10613,6 +10612,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) } break; case FORM_CHANGE_BATTLE_TURN_END: + case FORM_CHANGE_HIT_BY_MOVE: if (formChanges[i].param1 == GetBattlerAbility(battler)) targetSpecies = formChanges[i].targetSpecies; break; diff --git a/src/berry.c b/src/berry.c index e66b106ca9..9f187bd1e2 100644 --- a/src/berry.c +++ b/src/berry.c @@ -2383,6 +2383,7 @@ static u8 GetTreeMutationValue(u8 id) return 0; myMutation.asField.a = tree->mutationA; myMutation.asField.b = tree->mutationB; + myMutation.asField.unused = 0; return sBerryMutations[myMutation.value - 1][2]; #else return 0; diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index bc66e64123..f15a9b5c2d 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -3146,115 +3146,115 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar const u8 gMonFootprint_Unown[] = INCBIN_U8("graphics/pokemon/unown/footprint.1bpp"); #endif //P_FOOTPRINTS - const u32 gMonFrontPic_UnownA[] = INCBIN_U32("graphics/pokemon/unown/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownA[] = INCBIN_U32("graphics/pokemon/unown/front.4bpp.lz"); const u32 gMonBackPic_UnownA[] = INCBIN_U32("graphics/pokemon/unown/back.4bpp.lz"); const u8 gMonIcon_UnownA[] = INCBIN_U8("graphics/pokemon/unown/icon.4bpp"); - const u32 gMonFrontPic_UnownB[] = INCBIN_U32("graphics/pokemon/unown/b/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownB[] = INCBIN_U32("graphics/pokemon/unown/b/front.4bpp.lz"); const u32 gMonBackPic_UnownB[] = INCBIN_U32("graphics/pokemon/unown/b/back.4bpp.lz"); const u8 gMonIcon_UnownB[] = INCBIN_U8("graphics/pokemon/unown/b/icon.4bpp"); - const u32 gMonFrontPic_UnownC[] = INCBIN_U32("graphics/pokemon/unown/c/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownC[] = INCBIN_U32("graphics/pokemon/unown/c/front.4bpp.lz"); const u32 gMonBackPic_UnownC[] = INCBIN_U32("graphics/pokemon/unown/c/back.4bpp.lz"); const u8 gMonIcon_UnownC[] = INCBIN_U8("graphics/pokemon/unown/c/icon.4bpp"); - const u32 gMonFrontPic_UnownD[] = INCBIN_U32("graphics/pokemon/unown/d/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownD[] = INCBIN_U32("graphics/pokemon/unown/d/front.4bpp.lz"); const u32 gMonBackPic_UnownD[] = INCBIN_U32("graphics/pokemon/unown/d/back.4bpp.lz"); const u8 gMonIcon_UnownD[] = INCBIN_U8("graphics/pokemon/unown/d/icon.4bpp"); - const u32 gMonFrontPic_UnownE[] = INCBIN_U32("graphics/pokemon/unown/e/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownE[] = INCBIN_U32("graphics/pokemon/unown/e/front.4bpp.lz"); const u32 gMonBackPic_UnownE[] = INCBIN_U32("graphics/pokemon/unown/e/back.4bpp.lz"); const u8 gMonIcon_UnownE[] = INCBIN_U8("graphics/pokemon/unown/e/icon.4bpp"); - const u32 gMonFrontPic_UnownF[] = INCBIN_U32("graphics/pokemon/unown/f/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownF[] = INCBIN_U32("graphics/pokemon/unown/f/front.4bpp.lz"); const u32 gMonBackPic_UnownF[] = INCBIN_U32("graphics/pokemon/unown/f/back.4bpp.lz"); const u8 gMonIcon_UnownF[] = INCBIN_U8("graphics/pokemon/unown/f/icon.4bpp"); - const u32 gMonFrontPic_UnownG[] = INCBIN_U32("graphics/pokemon/unown/g/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownG[] = INCBIN_U32("graphics/pokemon/unown/g/front.4bpp.lz"); const u32 gMonBackPic_UnownG[] = INCBIN_U32("graphics/pokemon/unown/g/back.4bpp.lz"); const u8 gMonIcon_UnownG[] = INCBIN_U8("graphics/pokemon/unown/g/icon.4bpp"); - const u32 gMonFrontPic_UnownH[] = INCBIN_U32("graphics/pokemon/unown/h/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownH[] = INCBIN_U32("graphics/pokemon/unown/h/front.4bpp.lz"); const u32 gMonBackPic_UnownH[] = INCBIN_U32("graphics/pokemon/unown/h/back.4bpp.lz"); const u8 gMonIcon_UnownH[] = INCBIN_U8("graphics/pokemon/unown/h/icon.4bpp"); - const u32 gMonFrontPic_UnownI[] = INCBIN_U32("graphics/pokemon/unown/i/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownI[] = INCBIN_U32("graphics/pokemon/unown/i/front.4bpp.lz"); const u32 gMonBackPic_UnownI[] = INCBIN_U32("graphics/pokemon/unown/i/back.4bpp.lz"); const u8 gMonIcon_UnownI[] = INCBIN_U8("graphics/pokemon/unown/i/icon.4bpp"); - const u32 gMonFrontPic_UnownJ[] = INCBIN_U32("graphics/pokemon/unown/j/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownJ[] = INCBIN_U32("graphics/pokemon/unown/j/front.4bpp.lz"); const u32 gMonBackPic_UnownJ[] = INCBIN_U32("graphics/pokemon/unown/j/back.4bpp.lz"); const u8 gMonIcon_UnownJ[] = INCBIN_U8("graphics/pokemon/unown/j/icon.4bpp"); - const u32 gMonFrontPic_UnownK[] = INCBIN_U32("graphics/pokemon/unown/k/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownK[] = INCBIN_U32("graphics/pokemon/unown/k/front.4bpp.lz"); const u32 gMonBackPic_UnownK[] = INCBIN_U32("graphics/pokemon/unown/k/back.4bpp.lz"); const u8 gMonIcon_UnownK[] = INCBIN_U8("graphics/pokemon/unown/k/icon.4bpp"); - const u32 gMonFrontPic_UnownL[] = INCBIN_U32("graphics/pokemon/unown/l/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownL[] = INCBIN_U32("graphics/pokemon/unown/l/front.4bpp.lz"); const u32 gMonBackPic_UnownL[] = INCBIN_U32("graphics/pokemon/unown/l/back.4bpp.lz"); const u8 gMonIcon_UnownL[] = INCBIN_U8("graphics/pokemon/unown/l/icon.4bpp"); - const u32 gMonFrontPic_UnownM[] = INCBIN_U32("graphics/pokemon/unown/m/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownM[] = INCBIN_U32("graphics/pokemon/unown/m/front.4bpp.lz"); const u32 gMonBackPic_UnownM[] = INCBIN_U32("graphics/pokemon/unown/m/back.4bpp.lz"); const u8 gMonIcon_UnownM[] = INCBIN_U8("graphics/pokemon/unown/m/icon.4bpp"); - const u32 gMonFrontPic_UnownN[] = INCBIN_U32("graphics/pokemon/unown/n/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownN[] = INCBIN_U32("graphics/pokemon/unown/n/front.4bpp.lz"); const u32 gMonBackPic_UnownN[] = INCBIN_U32("graphics/pokemon/unown/n/back.4bpp.lz"); const u8 gMonIcon_UnownN[] = INCBIN_U8("graphics/pokemon/unown/n/icon.4bpp"); - const u32 gMonFrontPic_UnownO[] = INCBIN_U32("graphics/pokemon/unown/o/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownO[] = INCBIN_U32("graphics/pokemon/unown/o/front.4bpp.lz"); const u32 gMonBackPic_UnownO[] = INCBIN_U32("graphics/pokemon/unown/o/back.4bpp.lz"); const u8 gMonIcon_UnownO[] = INCBIN_U8("graphics/pokemon/unown/o/icon.4bpp"); - const u32 gMonFrontPic_UnownP[] = INCBIN_U32("graphics/pokemon/unown/p/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownP[] = INCBIN_U32("graphics/pokemon/unown/p/front.4bpp.lz"); const u32 gMonBackPic_UnownP[] = INCBIN_U32("graphics/pokemon/unown/p/back.4bpp.lz"); const u8 gMonIcon_UnownP[] = INCBIN_U8("graphics/pokemon/unown/p/icon.4bpp"); - const u32 gMonFrontPic_UnownQ[] = INCBIN_U32("graphics/pokemon/unown/q/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownQ[] = INCBIN_U32("graphics/pokemon/unown/q/front.4bpp.lz"); const u32 gMonBackPic_UnownQ[] = INCBIN_U32("graphics/pokemon/unown/q/back.4bpp.lz"); const u8 gMonIcon_UnownQ[] = INCBIN_U8("graphics/pokemon/unown/q/icon.4bpp"); - const u32 gMonFrontPic_UnownR[] = INCBIN_U32("graphics/pokemon/unown/r/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownR[] = INCBIN_U32("graphics/pokemon/unown/r/front.4bpp.lz"); const u32 gMonBackPic_UnownR[] = INCBIN_U32("graphics/pokemon/unown/r/back.4bpp.lz"); const u8 gMonIcon_UnownR[] = INCBIN_U8("graphics/pokemon/unown/r/icon.4bpp"); - const u32 gMonFrontPic_UnownS[] = INCBIN_U32("graphics/pokemon/unown/s/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownS[] = INCBIN_U32("graphics/pokemon/unown/s/front.4bpp.lz"); const u32 gMonBackPic_UnownS[] = INCBIN_U32("graphics/pokemon/unown/s/back.4bpp.lz"); const u8 gMonIcon_UnownS[] = INCBIN_U8("graphics/pokemon/unown/s/icon.4bpp"); - const u32 gMonFrontPic_UnownT[] = INCBIN_U32("graphics/pokemon/unown/t/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownT[] = INCBIN_U32("graphics/pokemon/unown/t/front.4bpp.lz"); const u32 gMonBackPic_UnownT[] = INCBIN_U32("graphics/pokemon/unown/t/back.4bpp.lz"); const u8 gMonIcon_UnownT[] = INCBIN_U8("graphics/pokemon/unown/t/icon.4bpp"); - const u32 gMonFrontPic_UnownU[] = INCBIN_U32("graphics/pokemon/unown/u/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownU[] = INCBIN_U32("graphics/pokemon/unown/u/front.4bpp.lz"); const u32 gMonBackPic_UnownU[] = INCBIN_U32("graphics/pokemon/unown/u/back.4bpp.lz"); const u8 gMonIcon_UnownU[] = INCBIN_U8("graphics/pokemon/unown/u/icon.4bpp"); - const u32 gMonFrontPic_UnownV[] = INCBIN_U32("graphics/pokemon/unown/v/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownV[] = INCBIN_U32("graphics/pokemon/unown/v/front.4bpp.lz"); const u32 gMonBackPic_UnownV[] = INCBIN_U32("graphics/pokemon/unown/v/back.4bpp.lz"); const u8 gMonIcon_UnownV[] = INCBIN_U8("graphics/pokemon/unown/v/icon.4bpp"); - const u32 gMonFrontPic_UnownW[] = INCBIN_U32("graphics/pokemon/unown/w/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownW[] = INCBIN_U32("graphics/pokemon/unown/w/front.4bpp.lz"); const u32 gMonBackPic_UnownW[] = INCBIN_U32("graphics/pokemon/unown/w/back.4bpp.lz"); const u8 gMonIcon_UnownW[] = INCBIN_U8("graphics/pokemon/unown/w/icon.4bpp"); - const u32 gMonFrontPic_UnownX[] = INCBIN_U32("graphics/pokemon/unown/x/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownX[] = INCBIN_U32("graphics/pokemon/unown/x/front.4bpp.lz"); const u32 gMonBackPic_UnownX[] = INCBIN_U32("graphics/pokemon/unown/x/back.4bpp.lz"); const u8 gMonIcon_UnownX[] = INCBIN_U8("graphics/pokemon/unown/x/icon.4bpp"); - const u32 gMonFrontPic_UnownY[] = INCBIN_U32("graphics/pokemon/unown/y/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownY[] = INCBIN_U32("graphics/pokemon/unown/y/front.4bpp.lz"); const u32 gMonBackPic_UnownY[] = INCBIN_U32("graphics/pokemon/unown/y/back.4bpp.lz"); const u8 gMonIcon_UnownY[] = INCBIN_U8("graphics/pokemon/unown/y/icon.4bpp"); - const u32 gMonFrontPic_UnownZ[] = INCBIN_U32("graphics/pokemon/unown/z/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownZ[] = INCBIN_U32("graphics/pokemon/unown/z/front.4bpp.lz"); const u32 gMonBackPic_UnownZ[] = INCBIN_U32("graphics/pokemon/unown/z/back.4bpp.lz"); const u8 gMonIcon_UnownZ[] = INCBIN_U8("graphics/pokemon/unown/z/icon.4bpp"); - const u32 gMonFrontPic_UnownExclamationMark[] = INCBIN_U32("graphics/pokemon/unown/exclamation_mark/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownExclamationMark[] = INCBIN_U32("graphics/pokemon/unown/exclamation_mark/front.4bpp.lz"); const u32 gMonBackPic_UnownExclamationMark[] = INCBIN_U32("graphics/pokemon/unown/exclamation_mark/back.4bpp.lz"); const u8 gMonIcon_UnownExclamationMark[] = INCBIN_U8("graphics/pokemon/unown/exclamation_mark/icon.4bpp"); - const u32 gMonFrontPic_UnownQuestionMark[] = INCBIN_U32("graphics/pokemon/unown/question_mark/anim_front.4bpp.lz"); + const u32 gMonFrontPic_UnownQuestionMark[] = INCBIN_U32("graphics/pokemon/unown/question_mark/front.4bpp.lz"); const u32 gMonBackPic_UnownQuestionMark[] = INCBIN_U32("graphics/pokemon/unown/question_mark/back.4bpp.lz"); const u8 gMonIcon_UnownQuestionMark[] = INCBIN_U8("graphics/pokemon/unown/question_mark/icon.4bpp"); #endif //P_FAMILY_UNOWN diff --git a/src/data/items.h b/src/data/items.h index 3f2d0e80fa..07cf0b25ae 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -3688,7 +3688,7 @@ const struct Item gItemsInfo[] = .name = _("Dubious Disc"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( - "A transparent device\n" + "A clear device\n" "overflowing with\n" "dubious data."), .pocket = POCKET_ITEMS, @@ -9419,7 +9419,7 @@ const struct Item gItemsInfo[] = "Fires an icy cold\n" "beam that may\n" #if B_USE_FROSTBITE == TRUE - "give the foe frostbite."), + "inflict frostbite."), #else "freeze the foe."), #endif @@ -9435,11 +9435,13 @@ const struct Item gItemsInfo[] = .name = _("TM14"), .price = 5500, .description = COMPOUND_STRING( + #if B_USE_FROSTBITE == TRUE + "A snow-and-wind\n" + "attack that may\n" + "inflict frostbite."), + #else "A brutal snow-and-\n" "wind attack that\n" - #if B_USE_FROSTBITE == TRUE - "may give the foe frostbite."), - #else "may freeze the foe."), #endif .importance = I_REUSABLE_TMS, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index f8edc496de..a91f95a935 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1098,6 +1098,7 @@ static const struct FormChange sSandacondaFormChangeTable[] = static const struct FormChange sCramorantFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GULPING, ABILITY_GULP_MISSILE, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GORGING, ABILITY_GULP_MISSILE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_HIT_BY_MOVE, SPECIES_CRAMORANT, ABILITY_GULP_MISSILE}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, {FORM_CHANGE_END_BATTLE, SPECIES_CRAMORANT}, diff --git a/src/data/pokemon/species_info/gen_1_families.h b/src/data/pokemon/species_info/gen_1_families.h index 10910bf85a..e633c1a5a8 100644 --- a/src/data/pokemon/species_info/gen_1_families.h +++ b/src/data/pokemon/species_info/gen_1_families.h @@ -12043,7 +12043,11 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .baseSpeed = 90, .baseSpAttack = 100, .baseSpDefense = 120, + #if P_UPDATED_TYPES >= GEN_6 + .types = MON_TYPES(TYPE_PSYCHIC, TYPE_FAIRY), + #else .types = MON_TYPES(TYPE_PSYCHIC), + #endif .catchRate = 45, .expYield = (P_UPDATED_EXP_YIELDS >= GEN_5) ? 161 : 136, .evYield_SpDefense = 2, diff --git a/src/data/pokemon_graphics/front_pic_anims.h b/src/data/pokemon_graphics/front_pic_anims.h index 1817bc19c2..ab8707ac5d 100644 --- a/src/data/pokemon_graphics/front_pic_anims.h +++ b/src/data/pokemon_graphics/front_pic_anims.h @@ -2894,13 +2894,7 @@ static const union AnimCmd sAnim_Mismagius_1[] = #endif //P_FAMILY_MISDREAVUS #if P_FAMILY_UNOWN -static const union AnimCmd sAnim_Unown_1[] = -{ - ANIMCMD_FRAME(0, 30), - ANIMCMD_FRAME(1, 30), - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; +PLACEHOLDER_ANIM_SINGLE_FRAME(Unown); #endif //P_FAMILY_UNOWN #if P_FAMILY_WOBBUFFET diff --git a/src/level_caps.c b/src/level_caps.c index 81ffa7b090..61b4c8dc8f 100644 --- a/src/level_caps.c +++ b/src/level_caps.c @@ -49,15 +49,26 @@ u32 GetSoftLevelCapExpValue(u32 level, u32 expValue) if (B_EXP_CAP_TYPE == EXP_CAP_NONE) return expValue; - if (B_LEVEL_CAP_EXP_UP && level < currentLevelCap) + if (level < currentLevelCap) { - levelDifference = currentLevelCap - level; - if (levelDifference > ARRAY_COUNT(sExpScalingDown)) - return expValue + (expValue / sExpScalingUp[ARRAY_COUNT(sExpScalingDown) - 1]); + if (B_LEVEL_CAP_EXP_UP) + { + levelDifference = currentLevelCap - level; + if (levelDifference > ARRAY_COUNT(sExpScalingUp)) + return expValue + (expValue / sExpScalingUp[ARRAY_COUNT(sExpScalingUp) - 1]); + else + return expValue + (expValue / sExpScalingUp[levelDifference]); + } else - return expValue + (expValue / sExpScalingUp[levelDifference]); + { + return expValue; + } } - else if (B_EXP_CAP_TYPE == EXP_CAP_SOFT && level >= currentLevelCap) + else if (B_EXP_CAP_TYPE == EXP_CAP_HARD) + { + return 0; + } + else if (B_EXP_CAP_TYPE == EXP_CAP_SOFT) { levelDifference = level - currentLevelCap; if (levelDifference > ARRAY_COUNT(sExpScalingDown)) @@ -65,13 +76,8 @@ u32 GetSoftLevelCapExpValue(u32 level, u32 expValue) else return expValue / sExpScalingDown[levelDifference]; } - else if (level < currentLevelCap) + else { return expValue; } - else - { - return 0; - } - } diff --git a/src/pokemon.c b/src/pokemon.c index 9e0fbe6848..9663b2c317 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2532,6 +2532,7 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) case MON_DATA_EVOLUTION_TRACKER: evoTracker.asField.a = substruct1->evolutionTracker1; evoTracker.asField.b = substruct1->evolutionTracker2; + evoTracker.asField.unused = 0; retVal = evoTracker.value; break; default: @@ -3535,7 +3536,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); dataUnsigned = sExpCandyExperienceTable[param - 1] + GetMonData(mon, MON_DATA_EXP, NULL); - if (B_RARE_CANDY_CAP && EXP_CAP_HARD) + if (B_RARE_CANDY_CAP && B_EXP_CAP_TYPE == EXP_CAP_HARD) { u32 currentLevelCap = GetCurrentLevelCap(); if (dataUnsigned > gExperienceTables[gSpeciesInfo[species].growthRate][currentLevelCap]) diff --git a/src/script_menu.c b/src/script_menu.c index 021f23053c..b78f1ef112 100644 --- a/src/script_menu.c +++ b/src/script_menu.c @@ -329,7 +329,8 @@ void MultichoiceDynamic_DestroyStack(void) static void MultichoiceDynamic_MoveCursor(s32 itemIndex, bool8 onInit, struct ListMenu *list) { u8 taskId; - PlaySE(SE_SELECT); + if (!onInit) + PlaySE(SE_SELECT); taskId = FindTaskIdByFunc(Task_HandleScrollingMultichoiceInput); if (taskId != TASK_NONE) { diff --git a/test/battle/ability/gulp_missile.c b/test/battle/ability/gulp_missile.c index 680208506d..2ec9acc61b 100644 --- a/test/battle/ability/gulp_missile.c +++ b/test/battle/ability/gulp_missile.c @@ -116,9 +116,7 @@ SINGLE_BATTLE_TEST("(Gulp Missile) Cramorant in Gorging paralyzes the target if } SINGLE_BATTLE_TEST("(Gulp Missile) triggers even if the user is fainted by opposing mon") -{ - // See: https://github.com/rh-hideout/pokeemerald-expansion/issues/4143 - KNOWN_FAILING; +{ GIVEN { PLAYER(SPECIES_CRAMORANT) { HP(1); MaxHP(250); Ability(ABILITY_GULP_MISSILE); } PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/ai.c b/test/battle/ai.c index 0d890da466..11702a0c5a 100644 --- a/test/battle/ai.c +++ b/test/battle/ai.c @@ -830,3 +830,55 @@ AI_SINGLE_BATTLE_TEST("AI will choose Surf over Thunderbolt and Ice Beam if the TURN { EXPECT_MOVE(opponent, MOVE_SURF); } } } + +AI_SINGLE_BATTLE_TEST("AI will choose Scratch over Power-up Punch with Contrary") +{ + u32 ability; + + PARAMETRIZE {ability = ABILITY_SUCTION_CUPS; } + PARAMETRIZE {ability = ABILITY_CONTRARY; } + GIVEN { + ASSUME(gMovesInfo[MOVE_SCRATCH].power == 40); + ASSUME(gMovesInfo[MOVE_SCRATCH].type == TYPE_NORMAL); + ASSUME(gMovesInfo[MOVE_POWER_UP_PUNCH].power == 40); + ASSUME(gMovesInfo[MOVE_POWER_UP_PUNCH].type == TYPE_FIGHTING); + ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[0] == TYPE_WATER); + ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[1] == TYPE_WATER); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_SQUIRTLE) { }; + OPPONENT(SPECIES_MALAMAR) { Ability(ability); Moves(MOVE_SCRATCH, MOVE_POWER_UP_PUNCH); } + } WHEN { + TURN { + if (ability != ABILITY_CONTRARY) + EXPECT_MOVE(opponent, MOVE_POWER_UP_PUNCH); + else + EXPECT_MOVE(opponent, MOVE_SCRATCH); + } + } +} + +AI_SINGLE_BATTLE_TEST("AI will choose Superpower over Outrage with Contrary") +{ + u32 ability; + + PARAMETRIZE {ability = ABILITY_SUCTION_CUPS; } + PARAMETRIZE {ability = ABILITY_CONTRARY; } + GIVEN { + ASSUME(gMovesInfo[MOVE_SUPERPOWER].power == 120); + ASSUME(gMovesInfo[MOVE_SUPERPOWER].type == TYPE_FIGHTING); + ASSUME(gMovesInfo[MOVE_OUTRAGE].power == 120); + ASSUME(gMovesInfo[MOVE_OUTRAGE].type == TYPE_DRAGON); + ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[0] == TYPE_WATER); + ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[1] == TYPE_WATER); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_SQUIRTLE) { }; + OPPONENT(SPECIES_MALAMAR) { Ability(ability); Moves(MOVE_OUTRAGE, MOVE_SUPERPOWER); } + } WHEN { + TURN { + if (ability != ABILITY_CONTRARY) + EXPECT_MOVE(opponent, MOVE_OUTRAGE); + else + EXPECT_MOVE(opponent, MOVE_SUPERPOWER); + } + } +} diff --git a/test/battle/move_effect/belly_drum.c b/test/battle/move_effect/belly_drum.c index f45418fe8a..bbaa910d27 100644 --- a/test/battle/move_effect/belly_drum.c +++ b/test/battle/move_effect/belly_drum.c @@ -90,3 +90,17 @@ SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6") } } } + +SINGLE_BATTLE_TEST("Belly Drum's HP cost doesn't trigger effects that trigger on damage taken") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BELLY_DRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + MESSAGE("Wobbuffet cut its own HP and maximized ATTACK!"); + NOT MESSAGE("Wobbuffet's Air Balloon popped!"); + } +} diff --git a/test/battle/move_effect/fillet_away.c b/test/battle/move_effect/fillet_away.c index 8d770860a8..de203dbc5a 100644 --- a/test/battle/move_effect/fillet_away.c +++ b/test/battle/move_effect/fillet_away.c @@ -56,3 +56,19 @@ SINGLE_BATTLE_TEST("Fillet Away fails if user's current HP is half or less than } } } + +SINGLE_BATTLE_TEST("Fillet Away's HP cost doesn't trigger effects that trigger on damage taken") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FILLET_AWAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FILLET_AWAY, player); + MESSAGE("Wobbuffet's Attack sharply rose!"); + MESSAGE("Wobbuffet's Sp. Atk sharply rose!"); + MESSAGE("Wobbuffet's Speed sharply rose!"); + NOT MESSAGE("Wobbuffet's Air Balloon popped!"); + } +} diff --git a/test/battle/move_effect/future_sight.c b/test/battle/move_effect/future_sight.c index 6a163a736d..7ebac1ac97 100644 --- a/test/battle/move_effect/future_sight.c +++ b/test/battle/move_effect/future_sight.c @@ -132,3 +132,24 @@ SINGLE_BATTLE_TEST("Future Sight will miss timing if target faints before it is NOT MESSAGE("Foe Wynaut took the Future Sight attack!"); } } + +SINGLE_BATTLE_TEST("Future Sight will miss timing if target faints by residual damage") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(10); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_FUTURE_SIGHT); } + TURN { MOVE(player, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_WRAP); SEND_OUT(opponent, 1); } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player); + MESSAGE("Foe Wobbuffet fainted!"); + MESSAGE("2 sent out Wynaut!"); + NOT MESSAGE("Foe Wynaut took the Future Sight attack!"); + } +} diff --git a/test/battle/move_effect/shed_tail.c b/test/battle/move_effect/shed_tail.c index 5ff5746977..6f12d22eee 100644 --- a/test/battle/move_effect/shed_tail.c +++ b/test/battle/move_effect/shed_tail.c @@ -70,3 +70,18 @@ SINGLE_BATTLE_TEST("Shed Tail fails if there are no usable pokemon left") MESSAGE("But it failed!"); } } + +SINGLE_BATTLE_TEST("Shed Tail's HP cost doesn't trigger effects that trigger on damage taken") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SHED_TAIL); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHED_TAIL, player); + MESSAGE("Wobbuffet shed its tail to create a decoy!"); + NOT MESSAGE("Wobbuffet's Air Balloon popped!"); + } +} diff --git a/test/battle/move_effect/substitute.c b/test/battle/move_effect/substitute.c index c40711f583..a2e4c686ec 100644 --- a/test/battle/move_effect/substitute.c +++ b/test/battle/move_effect/substitute.c @@ -54,3 +54,17 @@ SINGLE_BATTLE_TEST("Substitute's HP cost can trigger a berry") MESSAGE("Wobbuffet's Sitrus Berry restored health!"); } } + +SINGLE_BATTLE_TEST("Substitute's HP cost doesn't trigger effects that trigger on damage taken") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, player); + MESSAGE("Wobbuffet made a SUBSTITUTE!"); + NOT MESSAGE("Wobbuffet's Air Balloon popped!"); + } +}