ported battle_ai_switch_items from pokeem

This commit is contained in:
jiangzhengwenjz
2019-08-03 23:59:41 +08:00
parent 8fed9a5f20
commit 5568895b04
10 changed files with 801 additions and 2720 deletions
+14 -14
View File
@@ -4847,7 +4847,7 @@ sub_8012434: @ 8012434
mov r10, r0
ldr r1, _080126D0 @ =gUnknown_2023DA8
mov r12, r1
ldr r0, _080126D4 @ =gUnknown_2023DA0
ldr r0, _080126D4 @ =gLastLandedMoves
mov r9, r0
ldr r1, _080126D8 @ =gLastMoves
mov r8, r1
@@ -4879,7 +4879,7 @@ _0801246C:
strh r3, [r0]
mov r1, r10
strh r3, [r1]
ldr r0, _080126F0 @ =gUnknown_2023DC0
ldr r0, _080126F0 @ =gLastHitBy
adds r1, r2, r0
movs r0, 0xFF
strb r0, [r1]
@@ -5173,14 +5173,14 @@ _080126AE:
.align 2, 0
_080126CC: .4byte gUnknown_2023DB0
_080126D0: .4byte gUnknown_2023DA8
_080126D4: .4byte gUnknown_2023DA0
_080126D4: .4byte gLastLandedMoves
_080126D8: .4byte gLastMoves
_080126DC: .4byte gDisableStructs
_080126E0: .4byte gUnknown_2023D90
_080126E4: .4byte gUnknown_2023DB8
_080126E8: .4byte gStatuses3
_080126EC: .4byte gUnknown_2023DD4
_080126F0: .4byte gUnknown_2023DC0
_080126F0: .4byte gLastHitBy
_080126F4: .4byte gBattleResources
_080126F8: .4byte gSideTimers
_080126FC: .4byte gSideStatuses
@@ -5585,7 +5585,7 @@ _08012A1A:
strh r2, [r0]
ldrb r0, [r1]
lsls r0, 1
ldr r6, _08012BB0 @ =gUnknown_2023DA0
ldr r6, _08012BB0 @ =gLastLandedMoves
adds r0, r6
strh r2, [r0]
ldrb r0, [r1]
@@ -5606,7 +5606,7 @@ _08012A1A:
strh r2, [r0]
mov r1, r12
ldrb r0, [r1]
ldr r2, _08012BC0 @ =gUnknown_2023DC0
ldr r2, _08012BC0 @ =gLastHitBy
adds r0, r2
movs r1, 0xFF
strb r1, [r0]
@@ -5758,11 +5758,11 @@ _08012BA0: .4byte gCurrentMove
_08012BA4: .4byte gBattleMoves
_08012BA8: .4byte gMoveResultFlags
_08012BAC: .4byte gLastMoves
_08012BB0: .4byte gUnknown_2023DA0
_08012BB0: .4byte gLastLandedMoves
_08012BB4: .4byte gUnknown_2023DA8
_08012BB8: .4byte gUnknown_2023DB0
_08012BBC: .4byte gUnknown_2023D90
_08012BC0: .4byte gUnknown_2023DC0
_08012BC0: .4byte gLastHitBy
_08012BC4: .4byte gBattleResources
thumb_func_end sub_8012760
@@ -6053,7 +6053,7 @@ _08012CA8:
strh r2, [r0]
ldrb r0, [r7]
lsls r0, 1
ldr r1, _08012F90 @ =gUnknown_2023DA0
ldr r1, _08012F90 @ =gLastLandedMoves
adds r0, r1
strh r2, [r0]
ldrb r0, [r7]
@@ -6072,7 +6072,7 @@ _08012CA8:
adds r0, r1
strh r2, [r0]
ldrb r0, [r7]
ldr r2, _08012FA0 @ =gUnknown_2023DC0
ldr r2, _08012FA0 @ =gLastHitBy
adds r0, r2
movs r1, 0xFF
strb r1, [r0]
@@ -6250,11 +6250,11 @@ _08012F80: .4byte 0xfbffffff
_08012F84: .4byte gBattleStruct
_08012F88: .4byte 0xffff1fff
_08012F8C: .4byte gLastMoves
_08012F90: .4byte gUnknown_2023DA0
_08012F90: .4byte gLastLandedMoves
_08012F94: .4byte gUnknown_2023DA8
_08012F98: .4byte gUnknown_2023DB0
_08012F9C: .4byte gUnknown_2023D90
_08012FA0: .4byte gUnknown_2023DC0
_08012FA0: .4byte gLastHitBy
_08012FA4: .4byte gBattleResources
_08012FA8: .4byte gBaseStats
thumb_func_end sub_8012BC8
@@ -13836,7 +13836,7 @@ HandleAction_ActionFinished: @ 8016D70
ldr r5, _08016E04 @ =gBattleScripting
strb r1, [r5, 0x18]
strb r1, [r5, 0x19]
ldr r2, _08016E08 @ =gUnknown_2023DA0
ldr r2, _08016E08 @ =gLastLandedMoves
ldr r3, _08016E0C @ =gBattlerAttacker
ldrb r0, [r3]
lsls r0, 1
@@ -13875,7 +13875,7 @@ _08016DF8: .4byte gCurrentMove
_08016DFC: .4byte gBattleMoveDamage
_08016E00: .4byte gMoveResultFlags
_08016E04: .4byte gBattleScripting
_08016E08: .4byte gUnknown_2023DA0
_08016E08: .4byte gLastLandedMoves
_08016E0C: .4byte gBattlerAttacker
_08016E10: .4byte gUnknown_2023DA8
_08016E14: .4byte gBattleStruct
File diff suppressed because it is too large Load Diff
+44 -44
View File
@@ -370,7 +370,7 @@ _0801DA5E:
movs r1, 0x1
orrs r0, r1
strb r0, [r2]
ldr r1, _0801DAA4 @ =gUnknown_2023DA0
ldr r1, _0801DAA4 @ =gLastLandedMoves
ldr r3, _0801DAA8 @ =gBattlerTarget
ldrb r0, [r3]
lsls r0, 1
@@ -392,7 +392,7 @@ _0801DA94: .4byte gCurrentMove
_0801DA98: .4byte gBattleMons
_0801DA9C: .4byte gBattlerAttacker
_0801DAA0: .4byte gMoveResultFlags
_0801DAA4: .4byte gUnknown_2023DA0
_0801DAA4: .4byte gLastLandedMoves
_0801DAA8: .4byte gBattlerTarget
_0801DAAC: .4byte gUnknown_2023DA8
_0801DAB0: .4byte gBattleCommunication
@@ -458,7 +458,7 @@ JumpIfMoveFailed: @ 801DB10
ands r0, r1
cmp r0, 0
beq _0801DB70
ldr r1, _0801DB64 @ =gUnknown_2023DA0
ldr r1, _0801DB64 @ =gLastLandedMoves
ldr r3, _0801DB68 @ =gBattlerTarget
ldrb r0, [r3]
lsls r0, 1
@@ -484,7 +484,7 @@ JumpIfMoveFailed: @ 801DB10
.align 2, 0
_0801DB5C: .4byte gBattlescriptCurrInstr
_0801DB60: .4byte gMoveResultFlags
_0801DB64: .4byte gUnknown_2023DA0
_0801DB64: .4byte gLastLandedMoves
_0801DB68: .4byte gBattlerTarget
_0801DB6C: .4byte gUnknown_2023DA8
_0801DB70:
@@ -2182,7 +2182,7 @@ _0801E8C0:
movs r1, 0x9
orrs r0, r1
strb r0, [r2]
ldr r1, _0801E92C @ =gUnknown_2023DA0
ldr r1, _0801E92C @ =gLastLandedMoves
ldrb r0, [r4]
lsls r0, 1
adds r0, r1
@@ -2208,22 +2208,22 @@ _0801E91C: .4byte gBattleMoveDamage
_0801E920: .4byte gBattlerTarget
_0801E924: .4byte gLastUsedAbility
_0801E928: .4byte gMoveResultFlags
_0801E92C: .4byte gUnknown_2023DA0
_0801E92C: .4byte gLastLandedMoves
_0801E930: .4byte gUnknown_2023DA8
_0801E934: .4byte gBattleCommunication
_0801E938:
ldr r1, _0801E944 @ =gUnknown_824F050
ldr r1, _0801E944 @ =gTypeEffectiveness
adds r0, r3, r1
ldrb r0, [r0]
adds r2, r1, 0
b _0801E9B4
.align 2, 0
_0801E944: .4byte gUnknown_824F050
_0801E944: .4byte gTypeEffectiveness
_0801E948:
adds r3, 0x3
b _0801E9B0
_0801E94C:
ldr r5, _0801EA84 @ =gUnknown_824F050
ldr r5, _0801EA84 @ =gTypeEffectiveness
adds r0, r3, r5
ldrb r0, [r0]
cmp r0, r8
@@ -2272,7 +2272,7 @@ _0801E9A8:
adds r3, 0x3
ldr r5, _0801EA88 @ =gBattleMons
ldr r4, _0801EA8C @ =gBattlerTarget
ldr r2, _0801EA84 @ =gUnknown_824F050
ldr r2, _0801EA84 @ =gTypeEffectiveness
_0801E9B0:
adds r0, r3, r2
ldrb r0, [r0]
@@ -2339,7 +2339,7 @@ _0801EA10:
orrs r0, r4
mov r1, r8
strb r0, [r1]
ldr r1, _0801EAA4 @ =gUnknown_2023DA0
ldr r1, _0801EAA4 @ =gLastLandedMoves
ldrb r0, [r5]
lsls r0, 1
adds r0, r1
@@ -2384,7 +2384,7 @@ _0801EA70:
pop {r0}
bx r0
.align 2, 0
_0801EA84: .4byte gUnknown_824F050
_0801EA84: .4byte gTypeEffectiveness
_0801EA88: .4byte gBattleMons
_0801EA8C: .4byte gBattlerTarget
_0801EA90: .4byte gBattlerAttacker
@@ -2392,7 +2392,7 @@ _0801EA94: .4byte gCurrentMove
_0801EA98: .4byte gMoveResultFlags
_0801EA9C: .4byte gBattleMoves
_0801EAA0: .4byte gLastUsedAbility
_0801EAA4: .4byte gUnknown_2023DA0
_0801EAA4: .4byte gLastLandedMoves
_0801EAA8: .4byte gUnknown_2023DA8
_0801EAAC: .4byte gBattleCommunication
_0801EAB0: .4byte gProtectStructs
@@ -2473,13 +2473,13 @@ _0801EB40: .4byte gBattlerTarget
_0801EB44: .4byte gLastUsedAbility
_0801EB48: .4byte gBattleCommunication
_0801EB4C:
ldr r1, _0801EB58 @ =gUnknown_824F050
ldr r1, _0801EB58 @ =gTypeEffectiveness
adds r0, r5, r1
ldrb r0, [r0]
adds r4, r1, 0
b _0801EC9E
.align 2, 0
_0801EB58: .4byte gUnknown_824F050
_0801EB58: .4byte gTypeEffectiveness
_0801EB5C:
adds r0, r5, r4
ldrb r0, [r0]
@@ -2919,7 +2919,7 @@ _0801EE94: .4byte gBattleMoves
_0801EE98: .4byte gBattleMons
_0801EE9C: .4byte gBattleMoveDamage
_0801EEA0:
ldr r1, _0801EEBC @ =gUnknown_824F050
ldr r1, _0801EEBC @ =gTypeEffectiveness
mov r2, r8
adds r0, r2, r1
ldrb r0, [r0]
@@ -2934,13 +2934,13 @@ _0801EEA0:
adds r0, r3, 0
b _0801EF3E
.align 2, 0
_0801EEBC: .4byte gUnknown_824F050
_0801EEBC: .4byte gTypeEffectiveness
_0801EEC0:
movs r0, 0x3
add r8, r0
b _0801EF28
_0801EEC6:
ldr r7, _0801EFC0 @ =gUnknown_824F050
ldr r7, _0801EFC0 @ =gTypeEffectiveness
mov r1, r8
adds r0, r1, r7
ldrb r0, [r0]
@@ -2988,7 +2988,7 @@ _0801EF20:
movs r1, 0x3
add r8, r1
ldr r5, _0801EFC4 @ =gBattleMons
ldr r2, _0801EFC0 @ =gUnknown_824F050
ldr r2, _0801EFC0 @ =gTypeEffectiveness
_0801EF28:
mov r3, r8
adds r0, r3, r2
@@ -3070,7 +3070,7 @@ _0801EFAE:
pop {r1}
bx r1
.align 2, 0
_0801EFC0: .4byte gUnknown_824F050
_0801EFC0: .4byte gTypeEffectiveness
_0801EFC4: .4byte gBattleMons
_0801EFC8: .4byte gBattleMoves
thumb_func_end TypeCalc
@@ -3129,7 +3129,7 @@ _0801F00C:
.align 2, 0
_0801F030: .4byte gBattleMoves
_0801F034:
ldr r0, _0801F0C0 @ =gUnknown_824F050
ldr r0, _0801F0C0 @ =gTypeEffectiveness
adds r1, r7, r0
ldrb r0, [r1]
cmp r0, 0xFF
@@ -3160,7 +3160,7 @@ _0801F05A:
_0801F06C:
adds r4, 0x3
adds r7, 0x3
ldr r1, _0801F0C0 @ =gUnknown_824F050
ldr r1, _0801F0C0 @ =gTypeEffectiveness
adds r0, r7, r1
ldrb r0, [r0]
cmp r0, 0xFF
@@ -3205,7 +3205,7 @@ _0801F0B0:
pop {r1}
bx r1
.align 2, 0
_0801F0C0: .4byte gUnknown_824F050
_0801F0C0: .4byte gTypeEffectiveness
_0801F0C4: .4byte gBattleMoves
thumb_func_end AI_TypeCalc
@@ -12325,7 +12325,7 @@ _08023966:
ands r1, r0
cmp r1, 0
bne _08023984
ldr r0, _080239C4 @ =gUnknown_2023DC0
ldr r0, _080239C4 @ =gLastHitBy
adds r0, r3, r0
mov r3, r9
ldrb r1, [r3]
@@ -12348,7 +12348,7 @@ _08023984:
ldr r0, _080239B8 @ =0x0000ffff
cmp r3, r0
bne _080239D4
ldr r1, _080239D0 @ =gUnknown_2023DA0
ldr r1, _080239D0 @ =gLastLandedMoves
ldrb r0, [r2]
lsls r0, 1
adds r0, r1
@@ -12359,12 +12359,12 @@ _080239B4: .4byte gLastMoves
_080239B8: .4byte 0x0000ffff
_080239BC: .4byte gUnknown_2023DB0
_080239C0: .4byte gBattlerTarget
_080239C4: .4byte gUnknown_2023DC0
_080239C4: .4byte gLastHitBy
_080239C8: .4byte gMoveResultFlags
_080239CC: .4byte gChosenMove
_080239D0: .4byte gUnknown_2023DA0
_080239D0: .4byte gLastLandedMoves
_080239D4:
ldr r0, _080239F8 @ =gUnknown_2023DA0
ldr r0, _080239F8 @ =gLastLandedMoves
ldrb r1, [r2]
lsls r1, 1
adds r1, r0
@@ -12383,7 +12383,7 @@ _080239D4:
ands r0, r3
b _08023A2A
.align 2, 0
_080239F8: .4byte gUnknown_2023DA0
_080239F8: .4byte gLastLandedMoves
_080239FC: .4byte gCurrentMove
_08023A00: .4byte gUnknown_2023DA8
_08023A04:
@@ -12402,7 +12402,7 @@ _08023A04:
.align 2, 0
_08023A1C: .4byte gUnknown_2023DA8
_08023A20:
ldr r0, _08023A38 @ =gUnknown_2023DA0
ldr r0, _08023A38 @ =gLastLandedMoves
ldrb r1, [r2]
lsls r1, 1
adds r1, r0
@@ -12416,7 +12416,7 @@ _08023A2C:
strb r0, [r4, 0x14]
b _08023BB4
.align 2, 0
_08023A38: .4byte gUnknown_2023DA0
_08023A38: .4byte gLastLandedMoves
_08023A3C: .4byte 0x0000ffff
_08023A40:
ldr r0, _08023B04 @ =gAbsentBattlerFlags
@@ -12699,7 +12699,7 @@ atk4A_typecalc2: @ 8023C38
movs r1, 0x9
orrs r0, r1
strb r0, [r2]
ldr r1, _08023CB4 @ =gUnknown_2023DA0
ldr r1, _08023CB4 @ =gLastLandedMoves
ldrb r0, [r7]
lsls r0, 1
adds r0, r1
@@ -12718,7 +12718,7 @@ _08023CA4: .4byte gBattleMons
_08023CA8: .4byte gBattlerTarget
_08023CAC: .4byte gLastUsedAbility
_08023CB0: .4byte gMoveResultFlags
_08023CB4: .4byte gUnknown_2023DA0
_08023CB4: .4byte gLastLandedMoves
_08023CB8: .4byte gBattleCommunication
_08023CBC:
ldr r0, _08023CC8 @ =gMoveResultFlags
@@ -12730,13 +12730,13 @@ _08023CBC:
.align 2, 0
_08023CC8: .4byte gMoveResultFlags
_08023CCC:
ldr r1, _08023CD8 @ =gUnknown_824F050
ldr r1, _08023CD8 @ =gTypeEffectiveness
adds r0, r5, r1
ldrb r0, [r0]
adds r6, r1, 0
b _08023D8E
.align 2, 0
_08023CD8: .4byte gUnknown_824F050
_08023CD8: .4byte gTypeEffectiveness
_08023CDC:
adds r0, r5, r6
ldrb r0, [r0]
@@ -12899,7 +12899,7 @@ _08023DF0:
movs r1, 0x1
orrs r0, r1
strb r0, [r2]
ldr r1, _08023E78 @ =gUnknown_2023DA0
ldr r1, _08023E78 @ =gLastLandedMoves
mov r2, r8
ldrb r0, [r2]
lsls r0, 1
@@ -12945,7 +12945,7 @@ _08023E68: .4byte gCurrentMove
_08023E6C: .4byte gBattleMoves
_08023E70: .4byte gLastUsedAbility
_08023E74: .4byte gMoveResultFlags
_08023E78: .4byte gUnknown_2023DA0
_08023E78: .4byte gLastLandedMoves
_08023E7C: .4byte gBattleCommunication
_08023E80: .4byte gProtectStructs
_08023E84: .4byte gBattlescriptCurrInstr
@@ -24813,7 +24813,7 @@ atkA6_settypetorandomresistance: @ 8029DAC
mov r6, r9
mov r5, r8
push {r5-r7}
ldr r1, _08029E14 @ =gUnknown_2023DA0
ldr r1, _08029E14 @ =gLastLandedMoves
ldr r4, _08029E18 @ =gBattlerAttacker
ldrb r0, [r4]
lsls r0, 1
@@ -24830,7 +24830,7 @@ atkA6_settypetorandomresistance: @ 8029DAC
cmp r0, 0
beq _08029E94
ldr r1, _08029E20 @ =gBattleMons
ldr r2, _08029E24 @ =gUnknown_2023DC0
ldr r2, _08029E24 @ =gLastHitBy
ldrb r0, [r4]
adds r0, r2
ldrb r2, [r0]
@@ -24860,11 +24860,11 @@ _08029DF6:
str r1, [r3]
b _08029F80
.align 2, 0
_08029E14: .4byte gUnknown_2023DA0
_08029E14: .4byte gLastLandedMoves
_08029E18: .4byte gBattlerAttacker
_08029E1C: .4byte 0x0000ffff
_08029E20: .4byte gBattleMons
_08029E24: .4byte gUnknown_2023DC0
_08029E24: .4byte gLastHitBy
_08029E28: .4byte gBattlescriptCurrInstr
_08029E2C:
mov r0, r12
@@ -24931,7 +24931,7 @@ _08029E9C:
bhi _08029E9C
lsls r0, r4, 1
adds r4, r0, r4
ldr r6, _08029F90 @ =gUnknown_824F050
ldr r6, _08029F90 @ =gTypeEffectiveness
adds r3, r4, r6
ldr r1, _08029F94 @ =gUnknown_2023DA8
ldr r2, _08029F98 @ =gBattlerAttacker
@@ -24979,7 +24979,7 @@ _08029EF8:
mov r8, r0
ldr r1, _08029FA4 @ =gBattlescriptCurrInstr
mov r12, r1
ldr r3, _08029F90 @ =gUnknown_824F050
ldr r3, _08029F90 @ =gTypeEffectiveness
adds r0, r4, 0x1
adds r0, r3
mov r9, r0
@@ -25050,7 +25050,7 @@ _08029F80:
pop {r0}
bx r0
.align 2, 0
_08029F90: .4byte gUnknown_824F050
_08029F90: .4byte gTypeEffectiveness
_08029F94: .4byte gUnknown_2023DA8
_08029F98: .4byte gBattlerAttacker
_08029F9C: .4byte gBattleMons
+1 -1
View File
@@ -233,7 +233,7 @@ gUnknown_824F020:: @ 824F020
gUnknown_824F048:: @ 824F048
.incbin "baserom.gba", 0x24F048, 0x8
gUnknown_824F050:: @ 824F050
gTypeEffectiveness:: @ 824F050
.incbin "baserom.gba", 0x24F050, 0x150
gUnknown_824F1A0:: @ 824F1A0
+2 -3
View File
@@ -175,9 +175,6 @@ struct TrainerMonNoItemDefaultMoves
u16 species;
};
u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg);
u8 GetBattlerSide(u8 bank);
struct TrainerMonItemDefaultMoves
{
u16 iv;
@@ -985,5 +982,7 @@ extern u8 gChosenMovePos;
extern u8 gUnknown_3004FFC[MAX_BATTLERS_COUNT];
extern u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT];
extern u16 gDynamicBasePower;
extern u16 gLastLandedMoves[MAX_BATTLERS_COUNT];
extern u8 gLastHitBy[MAX_BATTLERS_COUNT];
#endif // GUARD_BATTLE_H
+2
View File
@@ -59,4 +59,6 @@ extern const u8 gStatusConditionString_LoveJpn[8];
extern const u8 * const gStatusConditionStringsTable[7][2];
extern const u8 gTypeEffectiveness[336];
#endif // GUARD_BATTLE_2_H
+1 -1
View File
@@ -73,7 +73,7 @@ SECTIONS {
asm/battle_controller_player.o(.text);
src/battle_gfx_sfx_util.o(.text);
src/battle_controller_opponent.o(.text);
asm/battle_ai_switch_items.o(.text);
src/battle_ai_switch_items.o(.text);
asm/battle_controller_link_opponent.o(.text);
src/pokemon.o(.text);
src/trig.o(.text);
+734
View File
@@ -0,0 +1,734 @@
#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_controllers.h"
#include "pokemon.h"
#include "random.h"
#include "util.h"
#include "constants/abilities.h"
#include "constants/item_effects.h"
#include "constants/items.h"
#include "constants/moves.h"
#include "constants/species.h"
#include "constants/pokemon.h"
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng);
static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent);
static bool8 ShouldUseItem(void);
static bool8 ShouldSwitchIfPerishSong(void)
{
if (gStatuses3[gActiveBattler] & STATUS3_PERISH_SONG
&& gDisableStructs[gActiveBattler].perishSongTimer == 0)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
else
{
return FALSE;
}
}
static bool8 ShouldSwitchIfWonderGuard(void)
{
u8 opposingBattler;
u8 moveFlags;
s32 i, j;
u16 move;
if(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
return FALSE;
if (gBattleMons[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)].ability == ABILITY_WONDER_GUARD)
{
// Check if Pokemon has a super effective move.
for (opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT), i = 0; i < MAX_MON_MOVES; ++i)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE)
return FALSE;
}
// Find a Pokemon in the party that has a super effective move.
for (i = 0; i < PARTY_SIZE; ++i)
{
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
continue;
if (i == gBattlerPartyIndexes[gActiveBattler])
continue;
GetMonData(&gEnemyParty[i], MON_DATA_SPECIES); // Unused return value.
GetMonData(&gEnemyParty[i], MON_DATA_ABILITY_NUM); // Unused return value.
for (opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT), j = 0; j < MAX_MON_MOVES; ++j)
{
move = GetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j);
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE && Random() % 3 < 2)
{
// We found a mon.
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
}
}
return FALSE; // There is not a single Pokemon in the party that has a super effective move against a mon with Wonder Guard.
}
static bool8 FindMonThatAbsorbsOpponentsMove(void)
{
u8 battlerIn1, battlerIn2;
u8 absorbingTypeAbility;
s32 i;
if (HasSuperEffectiveMoveAgainstOpponents(TRUE) && Random() % 3)
return FALSE;
if (gLastLandedMoves[gActiveBattler] == MOVE_NONE)
return FALSE;
if (gLastLandedMoves[gActiveBattler] == 0xFFFF)
return FALSE;
if (gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0)
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)))])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)));
}
else
{
battlerIn1 = gActiveBattler;
battlerIn2 = gActiveBattler;
}
if (gBattleMoves[gLastLandedMoves[gActiveBattler]].type == TYPE_FIRE)
absorbingTypeAbility = ABILITY_FLASH_FIRE;
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].type == TYPE_WATER)
absorbingTypeAbility = ABILITY_WATER_ABSORB;
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].type == TYPE_ELECTRIC)
absorbingTypeAbility = ABILITY_VOLT_ABSORB;
else
return FALSE;
if (gBattleMons[gActiveBattler].ability == absorbingTypeAbility)
return FALSE;
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species;
u8 monAbility;
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
continue;
if (i == gBattlerPartyIndexes[battlerIn1])
continue;
if (i == gBattlerPartyIndexes[battlerIn2])
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
continue;
species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES);
if (GetMonData(&gEnemyParty[i], MON_DATA_ABILITY_NUM) != ABILITY_NONE)
monAbility = gBaseStats[species].abilities[1];
else
monAbility = gBaseStats[species].abilities[0];
if (absorbingTypeAbility == monAbility && Random() & 1)
{
// we found a mon
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
return FALSE;
}
static bool8 ShouldSwitchIfNaturalCure(void)
{
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP))
return FALSE;
if (gBattleMons[gActiveBattler].ability != ABILITY_NATURAL_CURE)
return FALSE;
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 2)
return FALSE;
if ((gLastLandedMoves[gActiveBattler] == MOVE_NONE || gLastLandedMoves[gActiveBattler] == 0xFFFF) && Random() & 1)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0 && Random() & 1)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_DOESNT_AFFECT_FOE, 1))
return TRUE;
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_NOT_VERY_EFFECTIVE, 1))
return TRUE;
if (Random() & 1)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
return FALSE;
}
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng)
{
u8 opposingBattler;
s32 i;
u8 moveFlags;
u16 move;
opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
if (!(gAbsentBattlerFlags & gBitTable[opposingBattler]))
{
for (i = 0; i < MAX_MON_MOVES; ++i)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE)
{
if (noRng)
return TRUE;
if (Random() % 10 != 0)
return TRUE;
}
}
}
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
return FALSE;
opposingBattler = GetBattlerAtPosition(BATTLE_PARTNER(B_POSITION_PLAYER_LEFT));
if (!(gAbsentBattlerFlags & gBitTable[opposingBattler]))
{
for (i = 0; i < MAX_MON_MOVES; ++i)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE)
{
if (noRng)
return TRUE;
if (Random() % 10 != 0)
return TRUE;
}
}
}
return FALSE;
}
static bool8 AreStatsRaised(void)
{
u8 buffedStatsValue = 0;
s32 i;
for (i = 0; i < NUM_BATTLE_STATS; ++i)
{
if (gBattleMons[gActiveBattler].statStages[i] > 6)
buffedStatsValue += gBattleMons[gActiveBattler].statStages[i] - 6;
}
return (buffedStatsValue > 3);
}
static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent)
{
u8 battlerIn1, battlerIn2;
s32 i, j;
u16 move;
u8 moveFlags;
if (gLastLandedMoves[gActiveBattler] == 0)
return FALSE;
if (gLastLandedMoves[gActiveBattler] == 0xFFFF)
return FALSE;
if (gLastHitBy[gActiveBattler] == 0xFF)
return FALSE;
if (gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0)
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)))])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)));
}
else
{
battlerIn1 = gActiveBattler;
battlerIn2 = gActiveBattler;
}
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species;
u8 monAbility;
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
continue;
if (i == gBattlerPartyIndexes[battlerIn1])
continue;
if (i == gBattlerPartyIndexes[battlerIn2])
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
continue;
species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES);
if (GetMonData(&gEnemyParty[i], MON_DATA_ABILITY_NUM) != ABILITY_NONE)
monAbility = gBaseStats[species].abilities[1];
else
monAbility = gBaseStats[species].abilities[0];
moveFlags = AI_TypeCalc(gLastLandedMoves[gActiveBattler], species, monAbility);
if (moveFlags & flags)
{
battlerIn1 = gLastHitBy[gActiveBattler];
for (j = 0; j < MAX_MON_MOVES; ++j)
{
move = GetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j);
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[battlerIn1].species, gBattleMons[battlerIn1].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE && Random() % moduloPercent == 0)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
}
}
return FALSE;
}
static bool8 ShouldSwitch(void)
{
u8 battlerIn1, battlerIn2;
s32 i;
s32 availableToSwitch;
if (gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
return FALSE;
if (gStatuses3[gActiveBattler] & STATUS3_ROOTED)
return FALSE;
if (AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBattler, ABILITY_SHADOW_TAG, 0, 0))
return FALSE;
if (AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBattler, ABILITY_ARENA_TRAP, 0, 0))
return FALSE; // misses the flying or levitate check
if (AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MAGNET_PULL, 0, 0))
{
if (gBattleMons[gActiveBattler].type1 == TYPE_STEEL)
return FALSE;
if (gBattleMons[gActiveBattler].type2 == TYPE_STEEL)
return FALSE;
}
availableToSwitch = 0;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK)])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK);
}
else
{
battlerIn2 = gActiveBattler;
battlerIn1 = gActiveBattler;
}
for (i = 0; i < PARTY_SIZE; ++i)
{
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
continue;
if (i == gBattlerPartyIndexes[battlerIn1])
continue;
if (i == gBattlerPartyIndexes[battlerIn2])
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
continue;
++availableToSwitch;
}
if (!availableToSwitch)
return FALSE;
if (ShouldSwitchIfPerishSong())
return TRUE;
if (ShouldSwitchIfWonderGuard())
return TRUE;
if (FindMonThatAbsorbsOpponentsMove())
return TRUE;
if (ShouldSwitchIfNaturalCure())
return TRUE;
if (HasSuperEffectiveMoveAgainstOpponents(FALSE))
return FALSE;
if (AreStatsRaised())
return FALSE;
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_DOESNT_AFFECT_FOE, 2)
|| FindMonWithFlagsAndSuperEffective(MOVE_RESULT_NOT_VERY_EFFECTIVE, 3))
return TRUE;
return FALSE;
}
void AI_TrySwitchOrUseItem(void)
{
u8 battlerIn1, battlerIn2;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
if (ShouldSwitch())
{
if (*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) == 6)
{
s32 monToSwitchId = GetMostSuitableMonToSwitchInto();
if (monToSwitchId == 6)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
battlerIn1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
battlerIn2 = battlerIn1;
}
else
{
battlerIn1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
battlerIn2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
}
for (monToSwitchId = 0; monToSwitchId < PARTY_SIZE; ++monToSwitchId)
{
if (GetMonData(&gEnemyParty[monToSwitchId], MON_DATA_HP) == 0)
continue;
if (monToSwitchId == gBattlerPartyIndexes[battlerIn1])
continue;
if (monToSwitchId == gBattlerPartyIndexes[battlerIn2])
continue;
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
continue;
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
continue;
break;
}
}
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = monToSwitchId;
}
*(gBattleStruct->monToSwitchIntoId + gActiveBattler) = *(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1));
return;
}
else if (ShouldUseItem())
{
return;
}
}
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (gActiveBattler ^ BIT_SIDE) << 8);
}
static void ModulateByTypeEffectiveness(u8 atkType, u8 defType1, u8 defType2, u8 *var)
{
s32 i = 0;
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
{
i += 3;
continue;
}
else if (TYPE_EFFECT_ATK_TYPE(i) == atkType)
{
// Check type1.
if (TYPE_EFFECT_DEF_TYPE(i) == defType1)
*var = (*var * TYPE_EFFECT_MULTIPLIER(i)) / 10;
// Check type2.
if (TYPE_EFFECT_DEF_TYPE(i) == defType2 && defType1 != defType2)
*var = (*var * TYPE_EFFECT_MULTIPLIER(i)) / 10;
}
i += 3;
}
}
u8 GetMostSuitableMonToSwitchInto(void)
{
u8 opposingBattler;
u8 bestDmg; // Note : should be changed to u32 for obvious reasons.
u8 bestMonId;
u8 battlerIn1, battlerIn2;
s32 i, j;
u8 invalidMons;
u16 move;
if (*(gBattleStruct->monToSwitchIntoId + gActiveBattler) != PARTY_SIZE)
return *(gBattleStruct->monToSwitchIntoId + gActiveBattler);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK)])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK);
// UB: It considers the opponent only player's side even though it can battle alongside player.
opposingBattler = Random() & BIT_FLANK;
if (gAbsentBattlerFlags & gBitTable[opposingBattler])
opposingBattler ^= BIT_FLANK;
}
else
{
opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
battlerIn1 = gActiveBattler;
battlerIn2 = gActiveBattler;
}
invalidMons = 0;
while (invalidMons != 0x3F) // All mons are invalid.
{
bestDmg = 0;
bestMonId = 6;
// Find the mon whose type is the most suitable offensively.
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES);
if (species != SPECIES_NONE
&& GetMonData(&gEnemyParty[i], MON_DATA_HP) != 0
&& !(gBitTable[i] & invalidMons)
&& gBattlerPartyIndexes[battlerIn1] != i
&& gBattlerPartyIndexes[battlerIn2] != i
&& i != *(gBattleStruct->monToSwitchIntoId + battlerIn1)
&& i != *(gBattleStruct->monToSwitchIntoId + battlerIn2))
{
u8 type1 = gBaseStats[species].type1;
u8 type2 = gBaseStats[species].type2;
u8 typeDmg = 10;
ModulateByTypeEffectiveness(gBattleMons[opposingBattler].type1, type1, type2, &typeDmg);
ModulateByTypeEffectiveness(gBattleMons[opposingBattler].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 != PARTY_SIZE)
{
for (i = 0; i < MAX_MON_MOVES; ++i)
{
move = GetMonData(&gEnemyParty[bestMonId], MON_DATA_MOVE1 + i);
if (move != MOVE_NONE && TypeCalc(move, gActiveBattler, opposingBattler) & MOVE_RESULT_SUPER_EFFECTIVE)
break;
}
if (i != MAX_MON_MOVES)
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;
gMoveResultFlags = 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 = 0; i < PARTY_SIZE; ++i)
{
if ((u16)(GetMonData(&gEnemyParty[i], MON_DATA_SPECIES)) == SPECIES_NONE)
continue;
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
continue;
if (gBattlerPartyIndexes[battlerIn1] == i)
continue;
if (gBattlerPartyIndexes[battlerIn2] == i)
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
continue;
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
continue;
for (j = 0; j < MAX_MON_MOVES; ++j)
{
move = GetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j);
gBattleMoveDamage = 0;
if (move != MOVE_NONE && gBattleMoves[move].power != 1)
{
AI_CalcDmg(gActiveBattler, opposingBattler);
TypeCalc(move, gActiveBattler, opposingBattler);
}
if (bestDmg < gBattleMoveDamage)
{
bestDmg = gBattleMoveDamage;
bestMonId = i;
}
}
}
return bestMonId;
}
static u8 GetAI_ItemType(u8 itemId, const u8 *itemEffect) // NOTE: should take u16 as item Id argument
{
if (itemId == ITEM_FULL_RESTORE)
return AI_ITEM_FULL_RESTORE;
else if (itemEffect[4] & ITEM4_HEAL_HP)
return AI_ITEM_HEAL_HP;
else if (itemEffect[3] & ITEM3_STATUS_ALL)
return AI_ITEM_CURE_CONDITION;
else if (itemEffect[0] & (ITEM0_HIGH_CRIT | ITEM0_X_ATTACK) || itemEffect[1] != 0 || itemEffect[2] != 0)
return AI_ITEM_X_STAT;
else if (itemEffect[3] & ITEM3_MIST)
return AI_ITEM_GUARD_SPECS;
else
return AI_ITEM_NOT_RECOGNIZABLE;
}
static bool8 ShouldUseItem(void)
{
s32 i;
u8 validMons = 0;
bool8 shouldUse = FALSE;
for (i = 0; i < PARTY_SIZE; ++i)
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) != 0
&& GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) != SPECIES_NONE
&& GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) != SPECIES_EGG)
++validMons;
for (i = 0; i < MAX_MON_MOVES; ++i)
{
u16 item;
const u8 *itemEffects;
u8 paramOffset;
u8 battlerSide;
if (i && validMons > (gBattleResources->battleHistory->itemsNo - i) + 1)
continue;
item = gBattleResources->battleHistory->trainerItems[i];
if (item == ITEM_NONE)
continue;
if (gItemEffectTable[item - ITEM_POTION] == NULL)
continue;
if (item == ITEM_ENIGMA_BERRY)
itemEffects = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
itemEffects = gItemEffectTable[item - ITEM_POTION];
*(gBattleStruct->AI_itemType + gActiveBattler / 2) = GetAI_ItemType(item, itemEffects);
switch (*(gBattleStruct->AI_itemType + gActiveBattler / 2))
{
case AI_ITEM_FULL_RESTORE:
if (gBattleMons[gActiveBattler].hp >= gBattleMons[gActiveBattler].maxHP / 4)
break;
if (gBattleMons[gActiveBattler].hp == 0)
break;
shouldUse = TRUE;
break;
case AI_ITEM_HEAL_HP:
paramOffset = GetItemEffectParamOffset(item, 4, 4);
if (paramOffset == 0)
break;
if (gBattleMons[gActiveBattler].hp == 0)
break;
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 4 || gBattleMons[gActiveBattler].maxHP - gBattleMons[gActiveBattler].hp > itemEffects[paramOffset])
shouldUse = TRUE;
break;
case AI_ITEM_CURE_CONDITION:
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x20;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_POISON && (gBattleMons[gActiveBattler].status1 & STATUS1_POISON || gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON))
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x10;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_BURN && gBattleMons[gActiveBattler].status1 & STATUS1_BURN)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x8;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x4;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[gActiveBattler].status1 & STATUS1_PARALYSIS)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x2;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x1;
shouldUse = TRUE;
}
break;
case AI_ITEM_X_STAT:
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
if (!gDisableStructs[gActiveBattler].isFirstTurn)
break;
if (itemEffects[0] & ITEM0_X_ATTACK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x1;
if (itemEffects[1] & ITEM1_X_DEFEND)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x2;
if (itemEffects[1] & ITEM1_X_SPEED)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x4;
if (itemEffects[2] & ITEM2_X_SPATK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x8;
if (itemEffects[2] & ITEM2_X_ACCURACY)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x20;
if (itemEffects[0] & ITEM0_HIGH_CRIT)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x80;
shouldUse = TRUE;
break;
case AI_ITEM_GUARD_SPECS:
battlerSide = GetBattlerSide(gActiveBattler);
if (gDisableStructs[gActiveBattler].isFirstTurn && gSideTimers[battlerSide].mistTimer == 0)
shouldUse = TRUE;
break;
case AI_ITEM_NOT_RECOGNIZABLE:
return FALSE;
}
if (shouldUse)
{
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
*(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2) = item;
gBattleResources->battleHistory->trainerItems[i] = 0;
return shouldUse;
}
}
return FALSE;
}
+1 -1
View File
@@ -1439,7 +1439,7 @@ static void OpponentHandleChoosePokemon(void)
battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
}
for (chosenMonId = 0; chosenMonId < 6; ++chosenMonId)
for (chosenMonId = 0; chosenMonId < PARTY_SIZE; ++chosenMonId)
if (GetMonData(&gEnemyParty[chosenMonId], MON_DATA_HP) != 0
&& chosenMonId != gBattlerPartyIndexes[battler1]
&& chosenMonId != gBattlerPartyIndexes[battler2])
+2 -2
View File
@@ -291,7 +291,7 @@ gUnknown_2023D90: @ 2023D90
gLastMoves: @ 2023D98
.space 0x8
gUnknown_2023DA0: @ 2023DA0
gLastLandedMoves: @ 2023DA0
.space 0x8
gUnknown_2023DA8: @ 2023DA8
@@ -303,7 +303,7 @@ gUnknown_2023DB0: @ 2023DB0
gUnknown_2023DB8: @ 2023DB8
.space 0x8
gUnknown_2023DC0: @ 2023DC0
gLastHitBy: @ 2023DC0
.space 0x4
gChosenMoveByBattler: @ 2023DC4