diff --git a/asm/battle_9.s b/asm/battle_9.s index 6d77d1593..0cf529bcc 100644 --- a/asm/battle_9.s +++ b/asm/battle_9.s @@ -5,726 +5,6 @@ .text - thumb_func_start sub_8063880 -sub_8063880: @ 8063880 - push {r4-r7,lr} - mov r7, r8 - push {r7} - ldr r4, =gActiveBank - ldrb r0, [r4] - bl GetBankIdentity - lsls r0, 24 - lsrs r6, r0, 24 - adds r5, r6, 0 - ldrb r0, [r4] - bl GetBankSide - lsls r0, 24 - ldr r1, =gEnemyParty - mov r8, r1 - cmp r0, 0 - bne _080638A8 - ldr r2, =gPlayerParty - mov r8, r2 -_080638A8: - ldr r7, =gBattleTypeFlags - ldr r0, [r7] - movs r1, 0x8 - ands r0, r1 - cmp r0, 0 - bne _080638B6 - b _080639E6 -_080638B6: - bl ShouldSwitch - lsls r0, 24 - cmp r0, 0 - bne _080638C2 - b _080639DC -_080638C2: - ldrb r0, [r4] - ldr r2, =gBattleStruct - ldr r1, [r2] - adds r0, r1 - movs r1, 0xA5 - lsls r1, 2 - adds r0, r1 - ldrb r0, [r0] - cmp r0, 0x6 - bne _080639B8 - bl sub_8063A90 - lsls r0, 24 - lsrs r4, r0, 24 - cmp r4, 0x6 - bne _080639A6 - ldr r0, [r7] - movs r1, 0x1 - ands r0, r1 - cmp r0, 0 - bne _08063910 - adds r0, r6, 0 - bl GetBankByIdentity - lsls r0, 24 - lsrs r5, r0, 24 - adds r6, r5, 0 - b _08063928 - .pool -_08063910: - adds r0, r5, 0 - bl GetBankByIdentity - lsls r0, 24 - lsrs r6, r0, 24 - movs r0, 0x2 - eors r5, r0 - adds r0, r5, 0 - bl GetBankByIdentity - lsls r0, 24 - lsrs r5, r0, 24 -_08063928: - ldr r0, =gBattleTypeFlags - ldr r0, [r0] - ldr r1, =0x00808000 - ands r0, r1 - cmp r0, 0 - beq _08063958 - ldr r0, =gActiveBank - ldrb r1, [r0] - movs r0, 0x2 - ands r0, r1 - cmp r0, 0 - bne _08063954 - movs r0, 0 - movs r7, 0x3 - b _0806395C - .pool -_08063954: - movs r0, 0x3 - b _0806395A -_08063958: - movs r0, 0 -_0806395A: - movs r7, 0x6 -_0806395C: - adds r4, r0, 0 - cmp r4, r7 - bge _080639A6 -_08063962: - movs r0, 0x64 - muls r0, r4 - add r0, r8 - movs r1, 0x39 - bl GetMonData - cmp r0, 0 - beq _080639A0 - ldr r1, =gBattlePartyID - lsls r0, r6, 1 - adds r0, r1 - ldrh r0, [r0] - cmp r4, r0 - beq _080639A0 - lsls r0, r5, 1 - adds r0, r1 - ldrh r0, [r0] - cmp r4, r0 - beq _080639A0 - ldr r0, =gBattleStruct - ldr r1, [r0] - adds r0, r6, r1 - adds r0, 0x5C - ldrb r0, [r0] - cmp r4, r0 - beq _080639A0 - adds r0, r5, r1 - adds r0, 0x5C - ldrb r0, [r0] - cmp r4, r0 - bne _080639A6 -_080639A0: - adds r4, 0x1 - cmp r4, r7 - blt _08063962 -_080639A6: - ldr r0, =gActiveBank - ldrb r0, [r0] - ldr r2, =gBattleStruct - ldr r1, [r2] - adds r0, r1 - movs r1, 0xA5 - lsls r1, 2 - adds r0, r1 - strb r4, [r0] -_080639B8: - ldr r0, =gActiveBank - ldrb r1, [r0] - ldr r0, [r2] - adds r0, r1, r0 - adds r1, r0, 0 - adds r1, 0x5C - movs r2, 0xA5 - lsls r2, 2 - adds r0, r2 - ldrb r0, [r0] - strb r0, [r1] - b _080639F8 - .pool -_080639DC: - bl sub_8063EE0 - lsls r0, 24 - cmp r0, 0 - bne _080639F8 -_080639E6: - ldr r0, =gActiveBank - ldrb r0, [r0] - movs r2, 0x1 - eors r2, r0 - lsls r2, 8 - movs r0, 0x1 - movs r1, 0 - bl EmitCmd_x21 -_080639F8: - pop {r3} - mov r8, r3 - pop {r4-r7} - pop {r0} - bx r0 - .pool - thumb_func_end sub_8063880 - - thumb_func_start sub_8063A08 -sub_8063A08: @ 8063A08 - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - sub sp, 0x4 - adds r6, r3, 0 - lsls r0, 24 - lsrs r0, 24 - str r0, [sp] - lsls r1, 24 - lsrs r1, 24 - mov r9, r1 - lsls r2, 24 - lsrs r2, 24 - mov r8, r2 - movs r7, 0 - ldr r0, =gTypeEffectiveness - mov r10, r0 - ldrb r0, [r0] - cmp r0, 0xFF - beq _08063A7A - mov r5, r10 -_08063A36: - ldrb r0, [r5] - cmp r0, 0xFE - beq _08063A6C - ldr r1, [sp] - cmp r0, r1 - bne _08063A6C - ldrb r4, [r5, 0x1] - cmp r4, r9 - bne _08063A56 - ldrb r1, [r6] - ldrb r0, [r5, 0x2] - muls r0, r1 - movs r1, 0xA - bl __divsi3 - strb r0, [r6] -_08063A56: - cmp r4, r8 - bne _08063A6C - cmp r9, r8 - beq _08063A6C - ldrb r1, [r6] - ldrb r0, [r5, 0x2] - muls r0, r1 - movs r1, 0xA - bl __divsi3 - strb r0, [r6] -_08063A6C: - adds r5, 0x3 - adds r7, 0x3 - mov r1, r10 - adds r0, r7, r1 - ldrb r0, [r0] - cmp r0, 0xFF - bne _08063A36 -_08063A7A: - add sp, 0x4 - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - .pool - thumb_func_end sub_8063A08 - - thumb_func_start sub_8063A90 -sub_8063A90: @ 8063A90 - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - sub sp, 0x24 - ldr r4, =gActiveBank - ldrb r2, [r4] - ldr r0, =gBattleStruct - ldr r0, [r0] - adds r0, r2, r0 - adds r1, r0, 0 - adds r1, 0x5C - ldrb r0, [r1] - cmp r0, 0x6 - beq _08063AB2 - b _08063E50 -_08063AB2: - ldr r0, =gBattleTypeFlags - ldr r1, [r0] - movs r0, 0x80 - lsls r0, 11 - ands r0, r1 - cmp r0, 0 - beq _08063AE0 - ldr r1, =gBattlePartyID - lsls r0, r2, 1 - adds r0, r1 - ldrb r0, [r0] - adds r0, 0x1 - lsls r0, 24 - lsrs r0, 24 - b _08063E50 - .pool -_08063AE0: - movs r0, 0x1 - ands r1, r0 - cmp r1, 0 - beq _08063B6C - str r2, [sp, 0x10] - adds r0, r2, 0 - bl GetBankIdentity - movs r5, 0x2 - eors r0, r5 - lsls r0, 24 - lsrs r0, 24 - bl GetBankByIdentity - ldr r1, =gAbsentBankFlags - ldrb r1, [r1] - ldr r2, =gBitTable - lsls r0, 24 - lsrs r0, 22 - adds r0, r2 - ldr r0, [r0] - ands r1, r0 - cmp r1, 0 - beq _08063B20 - ldrb r4, [r4] - str r4, [sp, 0x14] - b _08063B36 - .pool -_08063B20: - ldrb r0, [r4] - bl GetBankIdentity - eors r0, r5 - lsls r0, 24 - lsrs r0, 24 - bl GetBankByIdentity - lsls r0, 24 - lsrs r0, 24 - str r0, [sp, 0x14] -_08063B36: - bl Random - movs r3, 0x2 - ands r0, r3 - lsls r0, 24 - lsrs r0, 24 - str r0, [sp, 0x4] - ldr r0, =gAbsentBankFlags - ldrb r1, [r0] - ldr r2, =gBitTable - ldr r4, [sp, 0x4] - lsls r0, r4, 2 - adds r0, r2 - ldr r0, [r0] - ands r1, r0 - cmp r1, 0 - beq _08063B8A - eors r4, r3 - lsls r0, r4, 24 - lsrs r0, 24 - str r0, [sp, 0x4] - b _08063B8A - .pool -_08063B6C: - adds r0, r2, 0 - bl GetBankIdentity - movs r1, 0x1 - eors r0, r1 - lsls r0, 24 - lsrs r0, 24 - bl GetBankByIdentity - lsls r0, 24 - lsrs r0, 24 - str r0, [sp, 0x4] - ldrb r4, [r4] - str r4, [sp, 0x14] - str r4, [sp, 0x10] -_08063B8A: - ldr r0, =gBattleTypeFlags - ldr r0, [r0] - ldr r1, =0x00808000 - ands r0, r1 - cmp r0, 0 - beq _08063BC2 - ldr r2, =gActiveBank - ldrb r1, [r2] - movs r0, 0x2 - ands r0, r1 - cmp r0, 0 - bne _08063BB8 - movs r0, 0 - str r0, [sp, 0x18] - movs r1, 0x3 - str r1, [sp, 0x1C] - b _08063BCC - .pool -_08063BB8: - movs r4, 0x3 - str r4, [sp, 0x18] - movs r0, 0x6 - str r0, [sp, 0x1C] - b _08063BCC -_08063BC2: - movs r1, 0 - str r1, [sp, 0x18] - movs r2, 0x6 - str r2, [sp, 0x1C] - ldr r2, =gActiveBank -_08063BCC: - ldrb r0, [r2] - bl GetBankSide - lsls r0, 24 - ldr r4, =gEnemyParty - str r4, [sp, 0x20] - cmp r0, 0 - bne _08063BE0 - ldr r0, =gPlayerParty - str r0, [sp, 0x20] -_08063BE0: - movs r1, 0 - mov r9, r1 -_08063BE4: - movs r2, 0 - str r2, [sp, 0x8] - movs r4, 0x6 - str r4, [sp, 0xC] - ldr r7, [sp, 0x18] - ldr r0, [sp, 0x1C] - cmp r7, r0 - blt _08063BF6 - b _08063CF2 -_08063BF6: - lsls r0, r7, 2 - ldr r1, =gBitTable - adds r0, r1 - mov r8, r0 - mov r10, sp -_08063C00: - movs r0, 0x64 - muls r0, r7 - ldr r2, [sp, 0x20] - adds r4, r2, r0 - adds r0, r4, 0 - movs r1, 0xB - bl GetMonData - lsls r0, 16 - lsrs r5, r0, 16 - cmp r5, 0 - beq _08063CD8 - adds r0, r4, 0 - movs r1, 0x39 - bl GetMonData - cmp r0, 0 - beq _08063CD8 - mov r4, r8 - ldr r0, [r4] - mov r1, r9 - ands r0, r1 - cmp r0, 0 - bne _08063CD8 - ldr r1, =gBattlePartyID - ldr r2, [sp, 0x10] - lsls r0, r2, 1 - adds r0, r1 - ldrh r0, [r0] - cmp r0, r7 - beq _08063CD8 - ldr r4, [sp, 0x14] - lsls r0, r4, 1 - adds r0, r1 - ldrh r0, [r0] - cmp r0, r7 - beq _08063CD8 - ldr r0, =gBattleStruct - ldr r1, [r0] - adds r0, r2, r1 - adds r0, 0x5C - ldrb r0, [r0] - cmp r7, r0 - beq _08063CD8 - adds r0, r4, r1 - adds r0, 0x5C - ldrb r0, [r0] - cmp r7, r0 - beq _08063CD8 - ldr r1, =gBaseStats - lsls r0, r5, 3 - subs r0, r5 - lsls r0, 2 - adds r0, r1 - ldrb r5, [r0, 0x6] - ldrb r6, [r0, 0x7] - movs r0, 0xA - mov r1, r10 - strb r0, [r1] - movs r0, 0x58 - ldr r2, [sp, 0x4] - adds r4, r2, 0 - muls r4, r0 - ldr r0, =gBattleMons - adds r4, r0 - adds r0, r4, 0 - adds r0, 0x21 - ldrb r0, [r0] - adds r1, r5, 0 - adds r2, r6, 0 - mov r3, sp - bl sub_8063A08 - adds r4, 0x22 - ldrb r0, [r4] - adds r1, r5, 0 - adds r2, r6, 0 - mov r3, sp - bl sub_8063A08 - ldr r2, [sp, 0x8] - mov r1, r10 - ldrb r1, [r1] - cmp r2, r1 - bcs _08063CE6 - mov r2, r10 - ldrb r2, [r2] - str r2, [sp, 0x8] - lsls r0, r7, 24 - lsrs r0, 24 - str r0, [sp, 0xC] - b _08063CE6 - .pool -_08063CD8: - mov r4, r8 - ldr r0, [r4] - mov r1, r9 - orrs r1, r0 - lsls r0, r1, 24 - lsrs r0, 24 - mov r9, r0 -_08063CE6: - movs r2, 0x4 - add r8, r2 - adds r7, 0x1 - ldr r4, [sp, 0x1C] - cmp r7, r4 - blt _08063C00 -_08063CF2: - ldr r0, [sp, 0xC] - cmp r0, 0x6 - beq _08063D54 - movs r7, 0 - movs r0, 0x64 - ldr r1, [sp, 0xC] - adds r5, r1, 0 - muls r5, r0 -_08063D02: - adds r1, r7, 0 - adds r1, 0xD - ldr r2, [sp, 0x20] - adds r0, r2, r5 - bl GetMonData - lsls r0, 16 - lsrs r4, r0, 16 - cmp r4, 0 - beq _08063D2A - ldr r0, =gActiveBank - ldrb r1, [r0] - adds r0, r4, 0 - ldr r2, [sp, 0x4] - bl TypeCalc - movs r1, 0x2 - ands r1, r0 - cmp r1, 0 - bne _08063D30 -_08063D2A: - adds r7, 0x1 - cmp r7, 0x3 - ble _08063D02 -_08063D30: - cmp r7, 0x4 - beq _08063D36 - b _08063E4E -_08063D36: - ldr r4, [sp, 0xC] - lsls r0, r4, 2 - ldr r1, =gBitTable - adds r0, r1 - ldr r0, [r0] - mov r2, r9 - orrs r2, r0 - lsls r0, r2, 24 - lsrs r0, 24 - mov r9, r0 - b _08063D58 - .pool -_08063D54: - movs r4, 0x3F - mov r9, r4 -_08063D58: - mov r0, r9 - cmp r0, 0x3F - beq _08063D60 - b _08063BE4 -_08063D60: - ldr r0, =gDynamicBasePower - movs r1, 0 - strh r1, [r0] - ldr r0, =gBattleStruct - ldr r0, [r0] - strb r1, [r0, 0x13] - ldr r0, =gBattleScripting - movs r2, 0x1 - strb r2, [r0, 0xE] - ldr r0, =gBattleMoveFlags - strb r1, [r0] - ldr r0, =gCritMultiplier - strb r2, [r0] - movs r1, 0 - str r1, [sp, 0x8] - movs r2, 0x6 - str r2, [sp, 0xC] - ldr r7, [sp, 0x18] - ldr r4, [sp, 0x1C] - cmp r7, r4 - bge _08063E4E -_08063D8A: - movs r0, 0x64 - adds r6, r7, 0 - muls r6, r0 - ldr r0, [sp, 0x20] - adds r4, r0, r6 - adds r0, r4, 0 - movs r1, 0xB - bl GetMonData - lsls r0, 16 - adds r1, r7, 0x1 - mov r10, r1 - cmp r0, 0 - beq _08063E46 - adds r0, r4, 0 - movs r1, 0x39 - bl GetMonData - cmp r0, 0 - beq _08063E46 - ldr r1, =gBattlePartyID - ldr r2, [sp, 0x10] - lsls r0, r2, 1 - adds r0, r1 - ldrh r0, [r0] - cmp r0, r7 - beq _08063E46 - ldr r4, [sp, 0x14] - lsls r0, r4, 1 - adds r0, r1 - ldrh r0, [r0] - cmp r0, r7 - beq _08063E46 - ldr r0, =gBattleStruct - ldr r1, [r0] - adds r0, r2, r1 - adds r0, 0x5C - ldrb r0, [r0] - cmp r7, r0 - beq _08063E46 - adds r0, r4, r1 - adds r0, 0x5C - ldrb r0, [r0] - cmp r7, r0 - beq _08063E46 - movs r5, 0 - mov r9, r6 - ldr r0, =gBattleMoveDamage - mov r8, r0 - ldr r6, =gActiveBank -_08063DEE: - adds r1, r5, 0 - adds r1, 0xD - ldr r0, [sp, 0x20] - add r0, r9 - bl GetMonData - lsls r0, 16 - lsrs r4, r0, 16 - movs r0, 0 - mov r1, r8 - str r0, [r1] - cmp r4, 0 - beq _08063E2A - ldr r0, =gBattleMoves - lsls r1, r4, 1 - adds r1, r4 - lsls r1, 2 - adds r1, r0 - ldrb r0, [r1, 0x1] - cmp r0, 0x1 - beq _08063E2A - ldrb r0, [r6] - ldr r1, [sp, 0x4] - bl AI_CalcDmg - ldrb r1, [r6] - adds r0, r4, 0 - ldr r2, [sp, 0x4] - bl TypeCalc -_08063E2A: - mov r2, r8 - ldr r0, [r2] - ldr r4, [sp, 0x8] - cmp r4, r0 - bge _08063E40 - lsls r0, 24 - lsrs r0, 24 - str r0, [sp, 0x8] - lsls r0, r7, 24 - lsrs r0, 24 - str r0, [sp, 0xC] -_08063E40: - adds r5, 0x1 - cmp r5, 0x3 - ble _08063DEE -_08063E46: - mov r7, r10 - ldr r0, [sp, 0x1C] - cmp r7, r0 - blt _08063D8A -_08063E4E: - ldr r0, [sp, 0xC] -_08063E50: - add sp, 0x24 - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r1} - bx r1 - .pool - thumb_func_end sub_8063A90 thumb_func_start ai_identify_item_effect ai_identify_item_effect: @ 8063E84 @@ -783,8 +63,8 @@ _08063EDA: bx r1 thumb_func_end ai_identify_item_effect - thumb_func_start sub_8063EE0 -sub_8063EE0: @ 8063EE0 + thumb_func_start ShouldUseItem +ShouldUseItem: @ 8063EE0 push {r4-r7,lr} mov r7, r10 mov r6, r9 @@ -1361,6 +641,6 @@ _0806437E: pop {r4-r7} pop {r1} bx r1 - thumb_func_end sub_8063EE0 + thumb_func_end ShouldUseItem .align 2, 0 @ Don't pad with nop. diff --git a/asm/battle_controller_opponent.s b/asm/battle_controller_opponent.s index 3fbeac5c1..896d86d3a 100644 --- a/asm/battle_controller_opponent.s +++ b/asm/battle_controller_opponent.s @@ -5212,7 +5212,7 @@ sub_8061F90: @ 8061F90 thumb_func_start sub_8061F9C sub_8061F9C: @ 8061F9C push {lr} - bl sub_8063880 + bl AI_TrySwitchOrUseItem bl OpponentBufferExecCompleted pop {r0} bx r0 @@ -5456,7 +5456,7 @@ sub_8062188: @ 8062188 ldrb r0, [r1] cmp r0, 0x6 bne _08062254 - bl sub_8063A90 + bl GetMostSuitableMonToSwitchInto lsls r0, 24 lsrs r4, r0, 24 cmp r4, 0x6 diff --git a/asm/battle_controller_player_partner.s b/asm/battle_controller_player_partner.s index 269e5347b..8c080500e 100644 --- a/asm/battle_controller_player_partner.s +++ b/asm/battle_controller_player_partner.s @@ -4990,7 +4990,7 @@ sub_81BDAA0: @ 81BDAA0 thumb_func_start sub_81BDAAC sub_81BDAAC: @ 81BDAAC push {lr} - bl sub_8063880 + bl AI_TrySwitchOrUseItem bl PlayerPartnerBufferExecCompleted pop {r0} bx r0 @@ -5087,7 +5087,7 @@ sub_81BDB70: @ 81BDB70 thumb_func_start sub_81BDB7C sub_81BDB7C: @ 81BDB7C push {r4-r6,lr} - bl sub_8063A90 + bl GetMostSuitableMonToSwitchInto lsls r0, 24 lsrs r4, r0, 24 cmp r4, 0x6 diff --git a/include/battle.h b/include/battle.h index bb61c7043..0aa778fe2 100644 --- a/include/battle.h +++ b/include/battle.h @@ -5,6 +5,7 @@ #include "battle_util.h" #include "battle_script_commands.h" #include "battle_2.h" +#include "battle_ai_switch_items.h" /* Banks are a name given to what could be called a 'battlerId' or 'monControllerId'. diff --git a/include/battle_ai_switch_items.h b/include/battle_ai_switch_items.h new file mode 100644 index 000000000..5c78a5386 --- /dev/null +++ b/include/battle_ai_switch_items.h @@ -0,0 +1,7 @@ +#ifndef GUARD_BATTLE_AI_SWITCH_ITEMS_H +#define GUARD_BATTLE_AI_SWITCH_ITEMS_H + +void AI_TrySwitchOrUseItem(void); +u8 GetMostSuitableMonToSwitchInto(void); + +#endif // GUARD_BATTLE_AI_SWITCH_ITEMS_H diff --git a/src/battle_9.c b/src/battle_9.c index 1b1a4ab7c..291bfc9e3 100644 --- a/src/battle_9.c +++ b/src/battle_9.c @@ -16,13 +16,19 @@ extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT]; extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; extern u16 gUnknown_02024250[BATTLE_BANKS_COUNT]; extern u8 gUnknown_02024270[BATTLE_BANKS_COUNT]; +extern u16 gDynamicBasePower; +extern u8 gBattleMoveFlags; +extern u8 gCritMultiplier; +extern s32 gBattleMoveDamage; extern const struct BattleMove gBattleMoves[]; extern const struct BaseStats gBaseStats[]; +extern const u8 gTypeEffectiveness[]; // this file's functions bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng); bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent); +bool8 ShouldUseItem(void); bool8 ShouldSwitchIfPerishSong(void) { @@ -121,7 +127,7 @@ bool8 ShouldSwitchIfWonderGuard(void) return FALSE; // at this point there is not a single pokemon in the party that has a super effective move against a pokemon with wonder guard } -bool8 sub_8062E54(void) +bool8 FindMonThatAbsorbsOpponentsMove(void) { u8 bankIn1, bankIn2; u8 absorbingTypeAbility; @@ -430,13 +436,14 @@ bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent) bool8 ShouldSwitch(void) { u8 bankIn1, bankIn2; + u8 *activeBankPtr; // needed to match s32 firstId; s32 lastId; // + 1 struct Pokemon *party; s32 i; s32 availableToSwitch; - if (gBattleMons[gActiveBank].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) + if (gBattleMons[*(activeBankPtr = &gActiveBank)].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) return FALSE; if (gStatuses3[gActiveBank] & STATUS3_ROOTED) return FALSE; @@ -444,25 +451,29 @@ bool8 ShouldSwitch(void) return FALSE; if (AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBank, ABILITY_ARENA_TRAP, 0, 0)) return FALSE; // misses the flying or levitate check - if (AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, gActiveBank, ABILITY_MAGNET_PULL, 0, 0) - && (gBattleMons[gActiveBank].type1 == TYPE_STEEL || gBattleMons[gActiveBank].type2 == TYPE_STEEL)) - return FALSE; + if (AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MAGNET_PULL, 0, 0)) + { + if (gBattleMons[gActiveBank].type1 == TYPE_STEEL) + return FALSE; + if (gBattleMons[gActiveBank].type2 == TYPE_STEEL) + return FALSE; + } if (gBattleTypeFlags & BATTLE_TYPE_ARENA) return FALSE; availableToSwitch = 0; if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { - bankIn1 = gActiveBank; - if (gAbsentBankFlags & gBitTable[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)]) - bankIn2 = gActiveBank; + bankIn1 = *activeBankPtr; + if (gAbsentBankFlags & gBitTable[GetBankByIdentity(GetBankIdentity(*activeBankPtr) ^ BIT_MON)]) + bankIn2 = *activeBankPtr; else - bankIn2 = GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON); + bankIn2 = GetBankByIdentity(GetBankIdentity(*activeBankPtr) ^ BIT_MON); } else { - bankIn1 = gActiveBank; - bankIn2 = gActiveBank; + bankIn1 = *activeBankPtr; + bankIn2 = *activeBankPtr; } if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_x800000)) @@ -508,7 +519,7 @@ bool8 ShouldSwitch(void) return TRUE; if (ShouldSwitchIfWonderGuard()) return TRUE; - if (sub_8062E54()) + if (FindMonThatAbsorbsOpponentsMove()) return TRUE; if (ShouldSwitchIfNaturalCure()) return TRUE; @@ -516,10 +527,268 @@ bool8 ShouldSwitch(void) return FALSE; if (AreStatsRaised()) return FALSE; - if (FindMonWithFlagsAndSuperEffective(MOVESTATUS_NOTAFFECTED, 2)) - return TRUE; - if (FindMonWithFlagsAndSuperEffective(MOVESTATUS_NOTVERYEFFECTIVE, 3)) + if (FindMonWithFlagsAndSuperEffective(MOVESTATUS_NOTAFFECTED, 2) + || FindMonWithFlagsAndSuperEffective(MOVESTATUS_NOTVERYEFFECTIVE, 3)) return TRUE; return FALSE; } + +void AI_TrySwitchOrUseItem(void) +{ + struct Pokemon *party; + u8 bankIn1, bankIn2; + s32 firstId; + s32 lastId; // + 1 + u8 bankIdentity = GetBankIdentity(gActiveBank); + + if (GetBankSide(gActiveBank) == SIDE_PLAYER) + party = gPlayerParty; + else + party = gEnemyParty; + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + if (ShouldSwitch()) + { + if (*(gBattleStruct->field_294 + gActiveBank) == 6) + { + s32 monToSwitchId = GetMostSuitableMonToSwitchInto(); + if (monToSwitchId == 6) + { + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + bankIn1 = GetBankByIdentity(bankIdentity); + bankIn2 = bankIn1; + } + else + { + bankIn1 = GetBankByIdentity(bankIdentity); + bankIn2 = GetBankByIdentity(bankIdentity ^ BIT_MON); + } + + if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_x800000)) + { + if ((gActiveBank & BIT_MON) == 0) + firstId = 0, lastId = 3; + else + firstId = 3, lastId = 6; + } + else + { + firstId = 0, lastId = 6; + } + + for (monToSwitchId = firstId; monToSwitchId < lastId; monToSwitchId++) + { + if (GetMonData(&party[monToSwitchId], MON_DATA_HP) == 0) + continue; + if (monToSwitchId == gBattlePartyID[bankIn1]) + continue; + if (monToSwitchId == gBattlePartyID[bankIn2]) + continue; + if (monToSwitchId == *(gBattleStruct->field_5C + bankIn1)) + continue; + if (monToSwitchId == *(gBattleStruct->field_5C + bankIn2)) + continue; + + break; + } + } + + *(gBattleStruct->field_294 + gActiveBank) = monToSwitchId; + } + + *(gBattleStruct->field_5C + gActiveBank) = *(gBattleStruct->field_294 + gActiveBank); + return; + } + else if (ShouldUseItem()) + { + return; + } + } + + EmitCmd_x21(1, 0, (gActiveBank ^ BIT_SIDE) << 8); +} + +#define TYPE_FORESIGHT 0xFE +#define TYPE_ENDTABLE 0xFF + +static void ModulateByTypeEffectiveness(u8 atkType, u8 defType1, u8 defType2, u8 *var) +{ + s32 i = 0; + + while (gTypeEffectiveness[i] != TYPE_ENDTABLE) + { + if (gTypeEffectiveness[i] == TYPE_FORESIGHT) + { + i += 3; + continue; + } + else if (gTypeEffectiveness[i] == atkType) + { + // check type1 + if (gTypeEffectiveness[i + 1] == defType1) + *var = (*var * gTypeEffectiveness[i + 2]) / 10; + // check type2 + if (gTypeEffectiveness[i + 1] == defType2 && defType1 != defType2) + *var = (*var * gTypeEffectiveness[i + 2]) / 10; + } + i += 3; + } +} + +u8 GetMostSuitableMonToSwitchInto(void) +{ + u8 opposingBank; + u8 bestDmg; // note : should be changed to u32 for obvious reasons + u8 bestMonId; + u8 bankIn1, bankIn2; + s32 firstId; + s32 lastId; // + 1 + struct Pokemon *party; + s32 i, j; + u8 invalidMons; + u16 move; + + if (*(gBattleStruct->field_5C + gActiveBank) != 6) + return *(gBattleStruct->field_5C + gActiveBank); + if (gBattleTypeFlags & BATTLE_TYPE_ARENA) + return gBattlePartyID[gActiveBank] + 1; + + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + bankIn1 = gActiveBank; + if (gAbsentBankFlags & gBitTable[GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON)]) + bankIn2 = gActiveBank; + else + bankIn2 = GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_MON); + + // UB: It considers the opponent only player's side even though it can battle alongside player; + opposingBank = Random() & BIT_MON; + if (gAbsentBankFlags & gBitTable[opposingBank]) + opposingBank ^= BIT_MON; + } + else + { + opposingBank = GetBankByIdentity(GetBankIdentity(gActiveBank) ^ BIT_SIDE); + bankIn1 = gActiveBank; + bankIn2 = gActiveBank; + } + + if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_x800000)) + { + if ((gActiveBank & BIT_MON) == 0) + firstId = 0, lastId = 3; + else + firstId = 3, lastId = 6; + } + else + { + firstId = 0, lastId = 6; + } + + if (GetBankSide(gActiveBank) == SIDE_PLAYER) + party = gPlayerParty; + else + party = gEnemyParty; + + invalidMons = 0; + + while (invalidMons != 0x3F) // all mons are invalid + { + bestDmg = 0; + bestMonId = 6; + // find the mon which type is the most suitable offensively + for (i = firstId; i < lastId; i++) + { + u16 species = GetMonData(&party[i], MON_DATA_SPECIES); + if (species != SPECIES_NONE + && GetMonData(&party[i], MON_DATA_HP) != 0 + && !(gBitTable[i] & invalidMons) + && gBattlePartyID[bankIn1] != i + && gBattlePartyID[bankIn2] != i + && i != *(gBattleStruct->field_5C + bankIn1) + && i != *(gBattleStruct->field_5C + bankIn2)) + { + u8 type1 = gBaseStats[species].type1; + u8 type2 = gBaseStats[species].type2; + u8 typeDmg = 10; + ModulateByTypeEffectiveness(gBattleMons[opposingBank].type1, type1, type2, &typeDmg); + ModulateByTypeEffectiveness(gBattleMons[opposingBank].type2, type1, type2, &typeDmg); + if (bestDmg < typeDmg) + { + bestDmg = typeDmg; + bestMonId = i; + } + } + else + { + invalidMons |= gBitTable[i]; + } + } + + // ok, we know the mon has the right typing but does it have at least one super effective move? + if (bestMonId != 6) + { + for (i = 0; i < 4; i++) + { + move = GetMonData(&party[bestMonId], MON_DATA_MOVE1 + i); + if (move != MOVE_NONE && TypeCalc(move, gActiveBank, opposingBank) & MOVESTATUS_SUPEREFFECTIVE) + break; + } + + if (i != 4) + return bestMonId; // has both the typing and at least one super effective move + + invalidMons |= gBitTable[bestMonId]; // sorry buddy, we want something better + } + else + { + invalidMons = 0x3F; // no viable mon to switch + } + } + + gDynamicBasePower = 0; + gBattleStruct->dynamicMoveType = 0; + gBattleScripting.dmgMultiplier = 1; + gBattleMoveFlags = 0; + gCritMultiplier = 1; + bestDmg = 0; + bestMonId = 6; + + // if we couldn't find the best mon in terms of typing, find the one that deals most damage + for (i = firstId; i < lastId; i++) + { + if ((u16)(GetMonData(&party[i], MON_DATA_SPECIES)) == SPECIES_NONE) + continue; + if (GetMonData(&party[i], MON_DATA_HP) == 0) + continue; + if (gBattlePartyID[bankIn1] == i) + continue; + if (gBattlePartyID[bankIn2] == i) + continue; + if (i == *(gBattleStruct->field_5C + bankIn1)) + continue; + if (i == *(gBattleStruct->field_5C + bankIn2)) + continue; + + for (j = 0; j < 4; j++) + { + move = GetMonData(&party[i], MON_DATA_MOVE1 + j); + gBattleMoveDamage = 0; + if (move != MOVE_NONE && gBattleMoves[move].power != 1) + { + AI_CalcDmg(gActiveBank, opposingBank); + TypeCalc(move, gActiveBank, opposingBank); + } + if (bestDmg < gBattleMoveDamage) + { + bestDmg = gBattleMoveDamage; + bestMonId = i; + } + } + } + + return bestMonId; +}