From 15b91a3c89fc2f939b3bb235a5dfda2c2342ffb0 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sun, 2 Sep 2018 15:50:18 +0200 Subject: [PATCH] AI handling for new moves --- asm/macros/battle_ai_script.inc | 34 ++++-- data/battle_ai_scripts.s | 196 ++++++++++++++++++++++++++++---- src/battle_ai_script_commands.c | 78 +++++++++---- 3 files changed, 251 insertions(+), 57 deletions(-) diff --git a/asm/macros/battle_ai_script.inc b/asm/macros/battle_ai_script.inc index bc55db740..b7287d3f9 100644 --- a/asm/macros/battle_ai_script.inc +++ b/asm/macros/battle_ai_script.inc @@ -315,13 +315,13 @@ .macro if_effect param0, param1 .byte 0x37 - .byte \param0 + .2byte \param0 .4byte \param1 .endm .macro if_not_effect param0, param1 .byte 0x38 - .byte \param0 + .2byte \param0 .4byte \param1 .endm @@ -469,14 +469,14 @@ .macro if_move_flag flag jumpptr .byte 0x52 - .2byte \flag + .4byte \flag .4byte \jumpptr .endm .macro if_field_status flag jumpptr .byte 0x53 - .word \flag - .word \jumpptr + .4byte \flag + .4byte \jumpptr .endm .macro get_move_accuracy @@ -491,7 +491,7 @@ .macro call_if_move_flag flag ptr .byte 0x52 - .2byte \flag + .4byte \flag .4byte \ptr .endm @@ -559,17 +559,33 @@ .4byte \param2 .endm - .macro get_ally_chosen_move bank + .macro get_ally_chosen_move .byte 0x63 .endm - .macro if_has_no_attacking_moves bank, param1 + .macro if_has_no_attacking_moves battler, param1 .byte 0x64 - .byte \bank + .byte \battler .4byte \param1 .endm + .macro get_hazards_count battler, effect + .byte 0x65 + .byte \battler + .2byte \effect + .endm + + .macro if_doesnt_hold_berry battler, ptr + .byte 0x66 + .byte \battler + .4byte \ptr + .endm + @ useful script macros + .macro if_holds_no_item battler, ptr + if_holds_item \battler, 0, \ptr + .endm + .macro get_curr_move_type get_type AI_TYPE_MOVE .endm diff --git a/data/battle_ai_scripts.s b/data/battle_ai_scripts.s index 3d4f31018..5c8262260 100644 --- a/data/battle_ai_scripts.s +++ b/data/battle_ai_scripts.s @@ -50,58 +50,53 @@ AI_CheckBadMove: if_move MOVE_FISSURE, AI_CBM_CheckIfNegatesType if_move MOVE_HORN_DRILL, AI_CBM_CheckIfNegatesType get_how_powerful_move_is - if_equal 0, AI_CheckBadMove_CheckSoundproof + if_equal 0, AI_CheckBadMove_CheckEffect AI_CBM_CheckIfNegatesType: @ 82DBF92 if_type_effectiveness AI_EFFECTIVENESS_x0, Score_Minus10 + get_ability AI_USER + if_equal ABILITY_MOLD_BREAKER, AI_CheckBadMove_CheckEffect + if_equal ABILITY_TERAVOLT, AI_CheckBadMove_CheckEffect + if_equal ABILITY_TURBOBLAZE, AI_CheckBadMove_CheckEffect get_ability AI_TARGET if_equal ABILITY_VOLT_ABSORB, CheckIfVoltAbsorbCancelsElectric + if_equal ABILITY_LIGHTNING_ROD, CheckIfVoltAbsorbCancelsElectric + if_equal ABILITY_MOTOR_DRIVE, CheckIfVoltAbsorbCancelsElectric if_equal ABILITY_WATER_ABSORB, CheckIfWaterAbsorbCancelsWater + if_equal ABILITY_DRY_SKIN, CheckIfWaterAbsorbCancelsWater if_equal ABILITY_FLASH_FIRE, CheckIfFlashFireCancelsFire if_equal ABILITY_WONDER_GUARD, CheckIfWonderGuardCancelsMove if_equal ABILITY_LEVITATE, CheckIfLevitateCancelsGroundMove - goto AI_CheckBadMove_CheckSoundproof_ + if_equal ABILITY_SOUNDPROOF, CheckIfSoundproofCancelsMove + goto AI_CheckBadMove_CheckEffect + +CheckIfSoundproofCancelsMove: + if_move_flag FLAG_SOUND, Score_Minus10 + goto AI_CheckBadMove_CheckEffect CheckIfVoltAbsorbCancelsElectric: @ 82DBFBD get_curr_move_type - if_equal_ TYPE_ELECTRIC, Score_Minus12 - goto AI_CheckBadMove_CheckSoundproof_ + if_equal_ TYPE_ELECTRIC, AI_CheckBadMove_CheckEffect + goto AI_CheckBadMove_CheckEffect CheckIfWaterAbsorbCancelsWater: @ 82DBFCA get_curr_move_type if_equal_ TYPE_WATER, Score_Minus12 - goto AI_CheckBadMove_CheckSoundproof_ + goto AI_CheckBadMove_CheckEffect CheckIfFlashFireCancelsFire: @ 82DBFD7 get_curr_move_type if_equal_ TYPE_FIRE, Score_Minus12 - goto AI_CheckBadMove_CheckSoundproof_ + goto AI_CheckBadMove_CheckEffect CheckIfWonderGuardCancelsMove: @ 82DBFE4 - if_type_effectiveness AI_EFFECTIVENESS_x2, AI_CheckBadMove_CheckSoundproof_ + if_type_effectiveness AI_EFFECTIVENESS_x2, AI_CheckBadMove_CheckEffect goto Score_Minus10 CheckIfLevitateCancelsGroundMove: @ 82DBFEF get_curr_move_type if_equal_ TYPE_GROUND, Score_Minus10 -AI_CheckBadMove_CheckSoundproof_: @ 82DBFF7 - get_how_powerful_move_is - if_equal 0, AI_CheckBadMove_CheckSoundproof - -AI_CheckBadMove_CheckSoundproof: @ 82DBFFE - get_ability AI_TARGET - if_not_equal ABILITY_SOUNDPROOF, AI_CheckBadMove_CheckEffect - if_move MOVE_GROWL, Score_Minus10 - if_move MOVE_ROAR, Score_Minus10 - if_move MOVE_SING, Score_Minus10 - if_move MOVE_SUPERSONIC, Score_Minus10 - if_move MOVE_SCREECH, Score_Minus10 - if_move MOVE_SNORE, Score_Minus10 - if_move MOVE_UPROAR, Score_Minus10 - if_move MOVE_METAL_SOUND, Score_Minus10 - if_move MOVE_GRASS_WHISTLE, Score_Minus10 - AI_CheckBadMove_CheckEffect: @ 82DC045 if_effect EFFECT_SLEEP, AI_CBM_Sleep if_effect EFFECT_EXPLOSION, AI_CBM_Explosion @@ -212,8 +207,156 @@ AI_CheckBadMove_CheckEffect: @ 82DC045 if_effect EFFECT_WATER_SPORT, AI_CBM_WaterSport if_effect EFFECT_CALM_MIND, AI_CBM_CalmMind if_effect EFFECT_DRAGON_DANCE, AI_CBM_DragonDance + if_effect EFFECT_STICKY_WEB, AI_CBM_StickyWeb + if_effect EFFECT_STEALTH_ROCK, AI_CBM_StealthRock + if_effect EFFECT_TOXIC_SPIKES, AI_CBM_ToxicSpikes + if_effect EFFECT_AQUA_RING, AI_CBM_AquaRing + if_effect EFFECT_GRAVITY, AI_CBM_Gravity + if_effect EFFECT_EMBARGO, AI_CBM_Embargo + if_effect EFFECT_LUCKY_CHANT, AI_CBM_LuckyChant + if_effect EFFECT_HEAL_PULSE, Score_Minus5 + if_effect EFFECT_QUASH, AI_CBM_Quash + if_effect EFFECT_GASTRO_ACID, AI_CBM_GastroAcid + if_effect EFFECT_HEAL_BLOCK, AI_CBM_HealBlock + if_effect EFFECT_WORRY_SEED, AI_CBM_WorrySeed + if_effect EFFECT_MIRACLE_EYE, AI_CBM_MiracleEye + if_effect EFFECT_MAGNET_RISE, AI_CBM_MagnetRise + if_effect EFFECT_TELEKINESIS, AI_CBM_Telekinesis + if_effect EFFECT_MISTY_TERRAIN, AI_CBM_MistyTerrain + if_effect EFFECT_GRASSY_TERRAIN, AI_CBM_GrassyTerrain + if_effect EFFECT_ELECTRIC_TERRAIN, AI_CBM_ElectricTerrain + if_effect EFFECT_PSYCHIC_TERRAIN, AI_CBM_PsychicTerrain + if_effect EFFECT_QUIVER_DANCE, AI_CBM_QuiverDance + if_effect EFFECT_COIL, AI_CBM_Coil + if_effect EFFECT_TAILWIND, AI_CBM_Tailwind + if_effect EFFECT_SIMPLE_BEAM, AI_CBM_SimpleBeam + if_effect EFFECT_NATURAL_GIFT, AI_CBM_NaturalGift + if_effect EFFECT_FLING, AI_CBM_Fling + if_effect EFFECT_ATTACK_ACCURACY_UP, AI_CBM_AtkAccUp + if_effect EFFECT_ATTACK_SPATK_UP, AI_CBM_AtkSpAtkUp + end + +AI_CBM_AtkAccUp: + if_stat_level_not_equal AI_USER, STAT_ATK, 12, AI_Ret + if_stat_level_equal AI_USER, STAT_ACC, 12, Score_Minus10 + end + +AI_CBM_AtkSpAtkUp: + if_stat_level_not_equal AI_USER, STAT_ATK, 12, AI_Ret + if_stat_level_equal AI_USER, STAT_SPATK, 12, Score_Minus10 + end + +AI_CBM_Fling: + if_holds_no_item AI_USER, Score_Minus10 + if_ability AI_USER, ABILITY_KLUTZ, Score_Minus10 + if_status3 AI_USER, STATUS3_EMBARGO, Score_Minus10 + if_field_status STATUS_FIELD_MAGIC_ROOM, Score_Minus10 + end + +AI_CBM_NaturalGift: + if_doesnt_hold_berry AI_USER, Score_Minus10 + if_ability AI_USER, ABILITY_KLUTZ, Score_Minus10 + if_status3 AI_USER, STATUS3_EMBARGO, Score_Minus10 + if_field_status STATUS_FIELD_MAGIC_ROOM, Score_Minus10 + end + +AI_CBM_SimpleBeam: + if_ability AI_TARGET, ABILITY_SIMPLE, Score_Minus10 + end + +AI_CBM_Tailwind: + if_side_affecting AI_USER, SIDE_STATUS_TAILWIND, Score_Minus10 + end + +AI_CBM_QuiverDance: + if_stat_level_not_equal AI_USER, STAT_SPATK, 12, AI_Ret + if_stat_level_not_equal AI_USER, STAT_SPDEF, 12, AI_Ret + if_stat_level_equal AI_USER, STAT_SPEED, 12, Score_Minus10 + end + +AI_CBM_Coil: + if_stat_level_not_equal AI_USER, STAT_ATK, 12, AI_Ret + if_stat_level_not_equal AI_USER, STAT_DEF, 12, AI_Ret + if_stat_level_equal AI_USER, STAT_ACC, 12, Score_Minus10 + end + +AI_CBM_MistyTerrain: + if_field_status STATUS_FIELD_MISTY_TERRAIN, Score_Minus10 + end + +AI_CBM_GrassyTerrain: + if_field_status STATUS_FIELD_GRASSY_TERRAIN, Score_Minus10 + end + +AI_CBM_ElectricTerrain: + if_field_status STATUS_FIELD_ELECTRIC_TERRAIN, Score_Minus10 + end + +AI_CBM_PsychicTerrain: + if_field_status STATUS_FIELD_PSYCHIC_TERRAIN, Score_Minus10 + end + +AI_CBM_Quash: + if_not_double_battle Score_Minus10 + end + +AI_CBM_Telekinesis: + if_status3 AI_TARGET, STATUS3_TELEKINESIS, Score_Minus10 + end + +AI_CBM_MagnetRise: + if_status3 AI_USER, STATUS3_MAGNET_RISE, Score_Minus10 + end + +AI_CBM_MiracleEye: + if_status3 AI_TARGET, STATUS3_MIRACLE_EYED, Score_Minus10 + if_status2 AI_TARGET, STATUS2_FORESIGHT, Score_Minus10 + end + +AI_CBM_WorrySeed: + get_ability AI_TARGET + if_equal ABILITY_INSOMNIA, Score_Minus10 + if_equal ABILITY_VITAL_SPIRIT, Score_Minus10 + end + +AI_CBM_HealBlock: + if_status3 AI_TARGET, STATUS3_HEAL_BLOCK, Score_Minus10 + end + +AI_CBM_GastroAcid: + if_status3 AI_TARGET, STATUS3_GASTRO_ACID, Score_Minus10 + end + +AI_CBM_AquaRing: + if_status3 AI_USER, STATUS3_AQUA_RING, Score_Minus10 + end + +AI_CBM_LuckyChant: + if_side_affecting AI_USER, SIDE_STATUS_LUCKY_CHANT, Score_Minus10 + end + +AI_CBM_Embargo: + if_status3 AI_TARGET, STATUS3_EMBARGO, Score_Minus10 + end + +AI_CBM_Gravity: + if_field_status STATUS_FIELD_GRAVITY, Score_Minus10 + end + +AI_CBM_ToxicSpikes: + if_not_side_affecting AI_TARGET, SIDE_STATUS_TOXIC_SPIKES, AI_Ret + get_hazards_count AI_TARGET, EFFECT_TOXIC_SPIKES + if_equal 2, Score_Minus10 + end + +AI_CBM_StealthRock: + if_side_affecting AI_TARGET, SIDE_STATUS_STEALTH_ROCK, Score_Minus10 end +AI_CBM_StickyWeb: + if_side_affecting AI_TARGET, SIDE_STATUS_STICKY_WEB, Score_Minus10 + end + AI_CBM_Sleep: @ 82DC2D4 get_ability AI_TARGET if_equal ABILITY_INSOMNIA, Score_Minus10 @@ -441,11 +584,14 @@ AI_CBM_Curse: @ 82DC5BB end AI_CBM_Spikes: @ 82DC5CC - if_side_affecting AI_TARGET, SIDE_STATUS_SPIKES, Score_Minus10 + if_not_side_affecting AI_TARGET, SIDE_STATUS_SPIKES, AI_Ret + get_hazards_count AI_TARGET, EFFECT_SPIKES + if_equal 3, Score_Minus10 end AI_CBM_Foresight: @ 82DC5D7 if_status2 AI_TARGET, STATUS2_FORESIGHT, Score_Minus10 + if_status3 AI_TARGET, STATUS3_MIRACLE_EYED, Score_Minus10 end AI_CBM_PerishSong: @ 82DC5E2 diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 0817bbca0..999beafc6 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -155,6 +155,8 @@ static void BattleAICmd_if_flash_fired(void); static void BattleAICmd_if_holds_item(void); static void BattleAICmd_get_ally_chosen_move(void); static void BattleAICmd_if_has_no_attacking_moves(void); +static void BattleAICmd_get_hazards_count(void); +static void BattleAICmd_if_doesnt_hold_berry(void); // ewram EWRAM_DATA const u8 *gAIScriptPtr = NULL; @@ -266,6 +268,8 @@ static const BattleAICmdFunc sBattleAICmdTable[] = BattleAICmd_if_holds_item, // 0x62 BattleAICmd_get_ally_chosen_move, // 0x63 BattleAICmd_if_has_no_attacking_moves, // 0x64 + BattleAICmd_get_hazards_count, // 0x65 + BattleAICmd_if_doesnt_hold_berry, // 0x66 }; static const u16 sDiscouragedPowerfulMoveEffects[] = @@ -1815,18 +1819,18 @@ static void BattleAICmd_get_weather(void) static void BattleAICmd_if_effect(void) { - if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect == gAIScriptPtr[1]) - gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect == T1_READ_16(gAIScriptPtr + 1)) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else - gAIScriptPtr += 6; + gAIScriptPtr += 7; } static void BattleAICmd_if_not_effect(void) { - if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect != gAIScriptPtr[1]) - gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect != T1_READ_16(gAIScriptPtr + 1)) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else - gAIScriptPtr += 6; + gAIScriptPtr += 7; } static void BattleAICmd_if_stat_level_less_than(void) @@ -2047,8 +2051,7 @@ static void BattleAICmd_if_has_move_with_effect(void) case AI_TARGET_PARTNER: for (i = 0; i < 4; i++) { - // UB: checks sBattler_AI instead of gBattlerTarget. - if (gBattleMons[sBattler_AI].moves[i] != 0 && gBattleMoves[BATTLE_HISTORY->usedMoves[gBattlerTarget].moves[i]].effect == gAIScriptPtr[2]) + if (gBattleMons[gBattlerTarget].moves[i] != 0 && gBattleMoves[BATTLE_HISTORY->usedMoves[gBattlerTarget].moves[i]].effect == gAIScriptPtr[2]) break; } if (i == 4) @@ -2184,18 +2187,13 @@ static void BattleAICmd_if_holds_item(void) { u8 battlerId = BattleAI_GetWantedBattler(gAIScriptPtr[1]); u16 item; - u8 var1, var2; if ((battlerId & BIT_SIDE) == (sBattler_AI & BIT_SIDE)) item = gBattleMons[battlerId].item; else item = BATTLE_HISTORY->itemEffects[battlerId]; - // UB: doesn't properly read an unaligned u16 - var2 = gAIScriptPtr[2]; - var1 = gAIScriptPtr[3]; - - if ((var1 | var2) == item) + if (T1_READ_16(gAIScriptPtr + 2) == item) gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); else gAIScriptPtr += 8; @@ -2301,12 +2299,12 @@ static void BattleAICmd_get_protect_count(void) static void BattleAICmd_if_move_flag(void) { - u16 flag = T1_READ_16(gAIScriptPtr + 1); + u32 flag = T1_READ_32(gAIScriptPtr + 1); if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].flags & flag) - gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); else - gAIScriptPtr += 7; + gAIScriptPtr += 9; } static void BattleAICmd_if_field_status(void) @@ -2341,16 +2339,16 @@ static void BattleAICmd_call_if_eq(void) static void BattleAICmd_call_if_move_flag(void) { - u16 flag = T1_READ_16(gAIScriptPtr + 1); + u32 flag = T1_READ_32(gAIScriptPtr + 1); if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].flags & flag) { - AIStackPushVar(gAIScriptPtr + 7); - gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); + AIStackPushVar(gAIScriptPtr + 9); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); } else { - gAIScriptPtr += 7; + gAIScriptPtr += 9; } } @@ -2493,7 +2491,41 @@ static void BattleAICmd_if_has_no_attacking_moves(void) } if (i == 4) - gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else - gAIScriptPtr += 5; + gAIScriptPtr += 6; +} + +static void BattleAICmd_get_hazards_count(void) +{ + u8 battlerId = BattleAI_GetWantedBattler(gAIScriptPtr[1]); + u8 side = GetBattlerSide(battlerId); + + switch (T1_READ_16(gAIScriptPtr + 2)) + { + case EFFECT_SPIKES: + AI_THINKING_STRUCT->funcResult = gSideTimers[side].spikesAmount; + break; + case EFFECT_TOXIC_SPIKES: + AI_THINKING_STRUCT->funcResult = gSideTimers[side].toxicSpikesAmount; + break; + } + + gAIScriptPtr += 4; +} + +static void BattleAICmd_if_doesnt_hold_berry(void) +{ + u8 battlerId = BattleAI_GetWantedBattler(gAIScriptPtr[1]); + u16 item; + + if (IsBattlerAIControlled(battlerId)) + item = gBattleMons[battlerId].item; + else + item = BATTLE_HISTORY->itemEffects[battlerId]; + + if (ItemId_GetPocket(item) == POCKET_BERRIES) + gAIScriptPtr += 6; + else + T1_READ_PTR(gAIScriptPtr + 2); }