mirror of
https://github.com/thornAvery/kep-hack.git
synced 2025-09-17 02:40:50 +12:00

This is...most of the stuff necessary for the Battle Tent to work. I've faithfully restored most things so far, including doing a few grammar tweaks. Main issue is that we get a really strange softlock when the Pokemon selection menu comes up. Not sure why, but point is, it can't progress to the next bit for debugging like this. Committing now to ask for assistance.
781 lines
15 KiB
NASM
781 lines
15 KiB
NASM
; creates a set of moves that may be used and returns its address in hl
|
|
; unused slots are filled with 0, all used slots may be chosen with equal probability
|
|
AIEnemyTrainerChooseMoves:
|
|
ld a, $a
|
|
ld hl, wBuffer ; init temporary move selection array. Only the moves with the lowest numbers are chosen in the end
|
|
ld [hli], a ; move 1
|
|
ld [hli], a ; move 2
|
|
ld [hli], a ; move 3
|
|
ld [hl], a ; move 4
|
|
ld a, [wEnemyDisabledMove] ; forbid disabled move (if any)
|
|
swap a
|
|
and $f
|
|
jr z, .noMoveDisabled
|
|
ld hl, wBuffer
|
|
dec a
|
|
ld c, a
|
|
ld b, $0
|
|
add hl, bc ; advance pointer to forbidden move
|
|
ld [hl], $50 ; forbid (highly discourage) disabled move
|
|
.noMoveDisabled
|
|
ld hl, TrainerClassMoveChoiceModifications
|
|
ld a, [wTrainerClass]
|
|
ld b, a
|
|
.loopTrainerClasses
|
|
dec b
|
|
jr z, .readTrainerClassData
|
|
.loopTrainerClassData
|
|
ld a, [hli]
|
|
and a
|
|
jr nz, .loopTrainerClassData
|
|
jr .loopTrainerClasses
|
|
.readTrainerClassData
|
|
ld a, [hl]
|
|
and a
|
|
jp z, .useOriginalMoveSet
|
|
push hl
|
|
.nextMoveChoiceModification
|
|
pop hl
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .loopFindMinimumEntries
|
|
push hl
|
|
ld hl, AIMoveChoiceModificationFunctionPointers
|
|
dec a
|
|
add a
|
|
ld c, a
|
|
ld b, 0
|
|
add hl, bc ; skip to pointer
|
|
ld a, [hli] ; read pointer into hl
|
|
ld h, [hl]
|
|
ld l, a
|
|
ld de, .nextMoveChoiceModification ; set return address
|
|
push de
|
|
jp hl ; execute modification function
|
|
.loopFindMinimumEntries ; all entries will be decremented sequentially until one of them is zero
|
|
ld hl, wBuffer ; temp move selection array
|
|
ld de, wEnemyMonMoves ; enemy moves
|
|
ld c, NUM_MOVES
|
|
.loopDecrementEntries
|
|
ld a, [de]
|
|
inc de
|
|
and a
|
|
jr z, .loopFindMinimumEntries
|
|
dec [hl]
|
|
jr z, .minimumEntriesFound
|
|
inc hl
|
|
dec c
|
|
jr z, .loopFindMinimumEntries
|
|
jr .loopDecrementEntries
|
|
.minimumEntriesFound
|
|
ld a, c
|
|
.loopUndoPartialIteration ; undo last (partial) loop iteration
|
|
inc [hl]
|
|
dec hl
|
|
inc a
|
|
cp NUM_MOVES + 1
|
|
jr nz, .loopUndoPartialIteration
|
|
ld hl, wBuffer ; temp move selection array
|
|
ld de, wEnemyMonMoves ; enemy moves
|
|
ld c, NUM_MOVES
|
|
.filterMinimalEntries ; all minimal entries now have value 1. All other slots will be disabled (move set to 0)
|
|
ld a, [de]
|
|
and a
|
|
jr nz, .moveExisting
|
|
ld [hl], a
|
|
.moveExisting
|
|
ld a, [hl]
|
|
dec a
|
|
jr z, .slotWithMinimalValue
|
|
xor a
|
|
ld [hli], a ; disable move slot
|
|
jr .next
|
|
.slotWithMinimalValue
|
|
ld a, [de]
|
|
ld [hli], a ; enable move slot
|
|
.next
|
|
inc de
|
|
dec c
|
|
jr nz, .filterMinimalEntries
|
|
ld hl, wBuffer ; use created temporary array as move set
|
|
ret
|
|
.useOriginalMoveSet
|
|
ld hl, wEnemyMonMoves ; use original move set
|
|
ret
|
|
|
|
AIMoveChoiceModificationFunctionPointers:
|
|
dw AIMoveChoiceModification1
|
|
dw AIMoveChoiceModification2
|
|
dw AIMoveChoiceModification3
|
|
dw AIMoveChoiceModification4 ; unused, does nothing
|
|
|
|
; discourages moves that cause no damage but only a status ailment if player's mon already has one
|
|
AIMoveChoiceModification1:
|
|
ld a, [wBattleMonStatus]
|
|
and a
|
|
ret z ; return if no status ailment on player's mon
|
|
ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
|
|
ld de, wEnemyMonMoves ; enemy moves
|
|
ld b, NUM_MOVES + 1
|
|
.nextMove
|
|
dec b
|
|
ret z ; processed all 4 moves
|
|
inc hl
|
|
ld a, [de]
|
|
and a
|
|
ret z ; no more moves in move set
|
|
inc de
|
|
call ReadMove
|
|
ld a, [wEnemyMovePower]
|
|
and a
|
|
jr nz, .nextMove
|
|
ld a, [wEnemyMoveEffect]
|
|
push hl
|
|
push de
|
|
push bc
|
|
ld hl, StatusAilmentMoveEffects
|
|
ld de, 1
|
|
call IsInArray
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
jr nc, .nextMove
|
|
ld a, [hl]
|
|
add $5 ; heavily discourage move
|
|
ld [hl], a
|
|
jr .nextMove
|
|
|
|
StatusAilmentMoveEffects:
|
|
db EFFECT_01 ; unused sleep effect
|
|
db SLEEP_EFFECT
|
|
db POISON_EFFECT
|
|
db PARALYZE_EFFECT
|
|
db -1 ; end
|
|
|
|
; slightly encourage moves with specific effects.
|
|
; in particular, stat-modifying moves and other move effects
|
|
; that fall in-between
|
|
AIMoveChoiceModification2:
|
|
ld a, [wAILayer2Encouragement]
|
|
cp $1
|
|
ret nz
|
|
ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
|
|
ld de, wEnemyMonMoves ; enemy moves
|
|
ld b, NUM_MOVES + 1
|
|
.nextMove
|
|
dec b
|
|
ret z ; processed all 4 moves
|
|
inc hl
|
|
ld a, [de]
|
|
and a
|
|
ret z ; no more moves in move set
|
|
inc de
|
|
call ReadMove
|
|
ld a, [wEnemyMoveEffect]
|
|
cp ATTACK_UP1_EFFECT
|
|
jr c, .nextMove
|
|
cp BIDE_EFFECT
|
|
jr c, .preferMove
|
|
cp ATTACK_UP2_EFFECT
|
|
jr c, .nextMove
|
|
cp POISON_EFFECT
|
|
jr c, .preferMove
|
|
jr .nextMove
|
|
.preferMove
|
|
dec [hl] ; slightly encourage this move
|
|
jr .nextMove
|
|
|
|
; encourages moves that are effective against the player's mon (even if non-damaging).
|
|
; discourage damaging moves that are ineffective or not very effective against the player's mon,
|
|
; unless there's no damaging move that deals at least neutral damage
|
|
AIMoveChoiceModification3:
|
|
ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
|
|
ld de, wEnemyMonMoves ; enemy moves
|
|
ld b, NUM_MOVES + 1
|
|
.nextMove
|
|
dec b
|
|
ret z ; processed all 4 moves
|
|
inc hl
|
|
ld a, [de]
|
|
and a
|
|
ret z ; no more moves in move set
|
|
inc de
|
|
call ReadMove
|
|
push hl
|
|
push bc
|
|
push de
|
|
callfar AIGetTypeEffectiveness
|
|
pop de
|
|
pop bc
|
|
pop hl
|
|
ld a, [wTypeEffectiveness]
|
|
cp $10
|
|
jr z, .nextMove
|
|
jr c, .notEffectiveMove
|
|
dec [hl] ; slightly encourage this move
|
|
jr .nextMove
|
|
.notEffectiveMove ; discourages non-effective moves if better moves are available
|
|
push hl
|
|
push de
|
|
push bc
|
|
ld a, [wEnemyMoveType]
|
|
ld d, a
|
|
ld hl, wEnemyMonMoves ; enemy moves
|
|
ld b, NUM_MOVES + 1
|
|
ld c, $0
|
|
.loopMoves
|
|
dec b
|
|
jr z, .done
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .done
|
|
call ReadMove
|
|
ld a, [wEnemyMoveEffect]
|
|
cp SUPER_FANG_EFFECT
|
|
jr z, .betterMoveFound ; Super Fang is considered to be a better move
|
|
cp SPECIAL_DAMAGE_EFFECT
|
|
jr z, .betterMoveFound ; any special damage moves are considered to be better moves
|
|
cp FLY_EFFECT
|
|
jr z, .betterMoveFound ; Fly is considered to be a better move
|
|
ld a, [wEnemyMoveType]
|
|
cp d
|
|
jr z, .loopMoves
|
|
ld a, [wEnemyMovePower]
|
|
and a
|
|
jr nz, .betterMoveFound ; damaging moves of a different type are considered to be better moves
|
|
jr .loopMoves
|
|
.betterMoveFound
|
|
ld c, a
|
|
.done
|
|
ld a, c
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
and a
|
|
jr z, .nextMove
|
|
inc [hl] ; slightly discourage this move
|
|
jr .nextMove
|
|
AIMoveChoiceModification4:
|
|
ret
|
|
|
|
ReadMove:
|
|
push hl
|
|
push de
|
|
push bc
|
|
dec a
|
|
ld hl, Moves
|
|
ld bc, MOVE_LENGTH
|
|
call AddNTimes
|
|
ld de, wEnemyMoveNum
|
|
call CopyData
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
INCLUDE "data/trainers/move_choices.asm"
|
|
|
|
INCLUDE "data/trainers/pic_pointers_money.asm"
|
|
|
|
INCLUDE "data/trainers/names.asm"
|
|
|
|
INCLUDE "engine/battle/misc.asm"
|
|
|
|
INCLUDE "engine/battle/read_trainer_party.asm"
|
|
|
|
INCLUDE "data/trainers/special_moves.asm"
|
|
|
|
INCLUDE "data/trainers/parties.asm"
|
|
|
|
TrainerAI:
|
|
and a
|
|
ld a, [wIsInBattle]
|
|
dec a
|
|
ret z ; if not a trainer, we're done here
|
|
ld a, [wCurMap]
|
|
cp BATTLE_TENT
|
|
ret z ; if we are in battle tent, we are done
|
|
ld a, [wLinkState]
|
|
cp LINK_STATE_BATTLING
|
|
ret z ; if in a link battle, we're done as well
|
|
ld a, [wTrainerClass] ; what trainer class is this?
|
|
dec a
|
|
ld c, a
|
|
ld b, 0
|
|
ld hl, TrainerAIPointers
|
|
add hl, bc
|
|
add hl, bc
|
|
add hl, bc
|
|
ld a, [wAICount]
|
|
and a
|
|
ret z ; if no AI uses left, we're done here
|
|
inc hl
|
|
inc a
|
|
jr nz, .getpointer
|
|
dec hl
|
|
ld a, [hli]
|
|
ld [wAICount], a
|
|
.getpointer
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
call Random
|
|
jp hl
|
|
|
|
INCLUDE "data/trainers/ai_pointers.asm"
|
|
; when there's a +1 on the gym/e4 it's referring to the number of items to use - PvK
|
|
|
|
JugglerAI:
|
|
cp 25 percent + 1
|
|
ret nc
|
|
jp AISwitchIfEnoughMons
|
|
|
|
BlackbeltAI:
|
|
cp 13 percent - 1
|
|
ret nc
|
|
jp AIUseXAttack
|
|
|
|
GiovanniAI:
|
|
cp 25 percent + 1
|
|
ret nc
|
|
jp AIUseXAttack ; Used to use a Guard Spec. This will make the item use have a proper impact - healing doesn't feel right for a trainer fixated on strength.
|
|
|
|
CooltrainerMAI:
|
|
cp 25 percent + 1
|
|
ret nc
|
|
jp AIUseXAttack
|
|
|
|
CooltrainerFAI:
|
|
; The intended 25% chance to consider switching applies, this fixes a bug.
|
|
cp 25 percent + 1
|
|
ret nc ; fixes the bug
|
|
ld a, 10
|
|
call AICheckIfHPBelowFraction
|
|
jp c, AIUseHyperPotion
|
|
ld a, 5
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AISwitchIfEnoughMons
|
|
|
|
BrockAI:
|
|
; if his active monster has a status condition, use a full heal
|
|
ld a, [wEnemyMonStatus]
|
|
and a
|
|
ret z
|
|
jp AIUseFullHeal
|
|
|
|
MistyAI:
|
|
; cp 25 percent + 1
|
|
; ret nc
|
|
; jp AIUseXDefend old Misty AI
|
|
cp 25 percent + 1
|
|
ret nc
|
|
ld a, 10
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUsePotion ; Replicates Starmie using Recover, but in a more balanced manner. Unlike other trainers that heal, Misty will do this 26% of the time instead of 51%.
|
|
|
|
LtSurgeAI:
|
|
cp 25 percent + 1
|
|
ret nc
|
|
jp AIUseXSpecial ; Used to be an X Speed. His party is already fast, so this seems far more appropriate.
|
|
|
|
ErikaAI:
|
|
cp 50 percent + 1
|
|
ret nc
|
|
ld a, 10
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseSuperPotion
|
|
|
|
KogaAI:
|
|
; cp 25 percent + 1
|
|
; ret nc
|
|
; jp AIUseXAttack old AI
|
|
cp 50 percent + 1
|
|
ret nc
|
|
ld a, 10
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseSuperPotion ; Koga is weird - I don't think anything fits. X Attack is certainly not the move though...
|
|
|
|
BlaineAI:
|
|
cp 25 percent + 1
|
|
ret nc
|
|
ld a, 10
|
|
call AICheckIfHPBelowFraction
|
|
ret nc ; this fixes the super potion thing - PvK
|
|
jp AIUseHyperPotion ; Instead of a Super Potion though, let's give him this. More impactful for the sixth gym while staying true to the meme that everyone knows Gen 1 Blaine for.
|
|
|
|
SabrinaAI:
|
|
cp 25 percent + 1
|
|
ret nc
|
|
ld a, 10
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseHyperPotion
|
|
|
|
Rival2AI:
|
|
cp 13 percent - 1
|
|
ret nc
|
|
ld a, 5
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUsePotion
|
|
|
|
Rival3AI:
|
|
cp 13 percent - 1
|
|
ret nc
|
|
ld a, 5
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseFullRestore
|
|
|
|
; Elite Four members will use an associated X Item or a Full Restore.
|
|
LoreleiAI:
|
|
cp 15 percent + 1
|
|
ret nc
|
|
jp AIUseXSpecial
|
|
cp 50 percent + 1
|
|
ret nc
|
|
ld a, 5
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseFullRestore
|
|
|
|
BrunoAI:
|
|
;cp 25 percent + 1
|
|
;ret nc
|
|
; jp AIUseXDefend old ai...???
|
|
cp 15 percent + 1
|
|
ret nc
|
|
jp AIUseXAttack
|
|
cp 50 percent + 1
|
|
ret nc
|
|
ld a, 5
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseFullRestore
|
|
|
|
AgathaAI:
|
|
cp 8 percent
|
|
jp c, AISwitchIfEnoughMons
|
|
cp 15 percent + 1
|
|
ret nc
|
|
jp AIUseXAccuracy ; hahahahahahahaha
|
|
cp 50 percent + 1
|
|
ret nc
|
|
ld a, 4
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseFullRestore
|
|
|
|
LanceAI:
|
|
cp 15 percent + 1
|
|
ret nc
|
|
jp AIUseXSpecial
|
|
cp 50 percent + 1
|
|
ret nc
|
|
ld a, 5
|
|
call AICheckIfHPBelowFraction
|
|
ret nc
|
|
jp AIUseFullRestore
|
|
|
|
GenericAI:
|
|
and a ; clear carry
|
|
ret
|
|
|
|
; end of individual trainer AI routines
|
|
|
|
DecrementAICount:
|
|
ld hl, wAICount
|
|
dec [hl]
|
|
scf
|
|
ret
|
|
|
|
AIPlayRestoringSFX:
|
|
ld a, SFX_HEAL_AILMENT
|
|
jp PlaySoundWaitForCurrent
|
|
|
|
AIUseFullRestore:
|
|
call AICureStatus
|
|
ld a, FULL_RESTORE
|
|
ld [wAIItem], a
|
|
ld de, wHPBarOldHP
|
|
ld hl, wEnemyMonHP + 1
|
|
ld a, [hld]
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hl]
|
|
ld [de], a
|
|
inc de
|
|
ld hl, wEnemyMonMaxHP + 1
|
|
ld a, [hld]
|
|
ld [de], a
|
|
inc de
|
|
ld [wHPBarMaxHP], a
|
|
ld [wEnemyMonHP + 1], a
|
|
ld a, [hl]
|
|
ld [de], a
|
|
ld [wHPBarMaxHP+1], a
|
|
ld [wEnemyMonHP], a
|
|
jr AIPrintItemUseAndUpdateHPBar
|
|
|
|
AIUsePotion:
|
|
; enemy trainer heals his monster with a potion
|
|
ld a, POTION
|
|
ld b, 20
|
|
jr AIRecoverHP
|
|
|
|
AIUseSuperPotion:
|
|
; enemy trainer heals his monster with a super potion
|
|
ld a, SUPER_POTION
|
|
ld b, 50
|
|
jr AIRecoverHP
|
|
|
|
AIUseHyperPotion:
|
|
; enemy trainer heals his monster with a hyper potion
|
|
ld a, HYPER_POTION
|
|
ld b, 200
|
|
; fallthrough
|
|
|
|
AIRecoverHP:
|
|
; heal b HP and print "trainer used $(a) on pokemon!"
|
|
ld [wAIItem], a
|
|
ld hl, wEnemyMonHP + 1
|
|
ld a, [hl]
|
|
ld [wHPBarOldHP], a
|
|
add b
|
|
ld [hld], a
|
|
ld [wHPBarNewHP], a
|
|
ld a, [hl]
|
|
ld [wHPBarOldHP+1], a
|
|
ld [wHPBarNewHP+1], a
|
|
jr nc, .next
|
|
inc a
|
|
ld [hl], a
|
|
ld [wHPBarNewHP+1], a
|
|
.next
|
|
inc hl
|
|
ld a, [hld]
|
|
ld b, a
|
|
ld de, wEnemyMonMaxHP + 1
|
|
ld a, [de]
|
|
dec de
|
|
ld [wHPBarMaxHP], a
|
|
sub b
|
|
ld a, [hli]
|
|
ld b, a
|
|
ld a, [de]
|
|
ld [wHPBarMaxHP+1], a
|
|
sbc b
|
|
jr nc, AIPrintItemUseAndUpdateHPBar
|
|
inc de
|
|
ld a, [de]
|
|
dec de
|
|
ld [hld], a
|
|
ld [wHPBarNewHP], a
|
|
ld a, [de]
|
|
ld [hl], a
|
|
ld [wHPBarNewHP+1], a
|
|
; fallthrough
|
|
|
|
AIPrintItemUseAndUpdateHPBar:
|
|
call AIPrintItemUse_
|
|
hlcoord 2, 2
|
|
xor a
|
|
ld [wHPBarType], a
|
|
predef UpdateHPBar2
|
|
jp DecrementAICount
|
|
|
|
AISwitchIfEnoughMons:
|
|
; enemy trainer switches if there are 2 or more unfainted mons in party
|
|
ld a, [wEnemyPartyCount]
|
|
ld c, a
|
|
ld hl, wEnemyMon1HP
|
|
|
|
ld d, 0 ; keep count of unfainted monsters
|
|
|
|
; count how many monsters haven't fainted yet
|
|
.loop
|
|
ld a, [hli]
|
|
ld b, a
|
|
ld a, [hld]
|
|
or b
|
|
jr z, .Fainted ; has monster fainted?
|
|
inc d
|
|
.Fainted
|
|
push bc
|
|
ld bc, wEnemyMon2 - wEnemyMon1
|
|
add hl, bc
|
|
pop bc
|
|
dec c
|
|
jr nz, .loop
|
|
|
|
ld a, d ; how many available monsters are there?
|
|
cp 2 ; don't bother if only 1
|
|
jp nc, SwitchEnemyMon
|
|
and a
|
|
ret
|
|
|
|
SwitchEnemyMon:
|
|
|
|
; prepare to withdraw the active monster: copy hp, number, and status to roster
|
|
|
|
ld a, [wEnemyMonPartyPos]
|
|
ld hl, wEnemyMon1HP
|
|
ld bc, wEnemyMon2 - wEnemyMon1
|
|
call AddNTimes
|
|
ld d, h
|
|
ld e, l
|
|
ld hl, wEnemyMonHP
|
|
ld bc, 4
|
|
call CopyData
|
|
|
|
ld hl, AIBattleWithdrawText
|
|
call PrintText
|
|
|
|
; This wFirstMonsNotOutYet variable is abused to prevent the player from
|
|
; switching in a new mon in response to this switch.
|
|
ld a, 1
|
|
ld [wFirstMonsNotOutYet], a
|
|
callfar EnemySendOut
|
|
xor a
|
|
ld [wFirstMonsNotOutYet], a
|
|
|
|
ld a, [wLinkState]
|
|
cp LINK_STATE_BATTLING
|
|
ret z
|
|
scf
|
|
ret
|
|
|
|
AIBattleWithdrawText:
|
|
text_far _AIBattleWithdrawText
|
|
text_end
|
|
|
|
AIUseFullHeal:
|
|
call AIPlayRestoringSFX
|
|
call AICureStatus
|
|
ld a, FULL_HEAL
|
|
jp AIPrintItemUse
|
|
|
|
AICureStatus:
|
|
; cures the status of enemy's active pokemon
|
|
ld a, [wEnemyMonPartyPos]
|
|
ld hl, wEnemyMon1Status
|
|
ld bc, wEnemyMon2 - wEnemyMon1
|
|
call AddNTimes
|
|
xor a
|
|
ld [hl], a ; clear status in enemy team roster
|
|
ld [wEnemyMonStatus], a ; clear status of active enemy
|
|
ld hl, wEnemyBattleStatus3
|
|
res 0, [hl]
|
|
ret
|
|
|
|
AIUseXAccuracy: ; unused
|
|
call AIPlayRestoringSFX
|
|
ld hl, wEnemyBattleStatus2
|
|
set 0, [hl]
|
|
ld a, X_ACCURACY
|
|
jp AIPrintItemUse
|
|
|
|
AIUseGuardSpec:
|
|
call AIPlayRestoringSFX
|
|
ld hl, wEnemyBattleStatus2
|
|
set 1, [hl]
|
|
ld a, GUARD_SPEC
|
|
jp AIPrintItemUse
|
|
|
|
AIUseDireHit: ; unused
|
|
call AIPlayRestoringSFX
|
|
ld hl, wEnemyBattleStatus2
|
|
set 2, [hl]
|
|
ld a, DIRE_HIT
|
|
jp AIPrintItemUse
|
|
|
|
AICheckIfHPBelowFraction:
|
|
; return carry if enemy trainer's current HP is below 1 / a of the maximum
|
|
ldh [hDivisor], a
|
|
ld hl, wEnemyMonMaxHP
|
|
ld a, [hli]
|
|
ldh [hDividend], a
|
|
ld a, [hl]
|
|
ldh [hDividend + 1], a
|
|
ld b, 2
|
|
call Divide
|
|
ldh a, [hQuotient + 3]
|
|
ld c, a
|
|
ldh a, [hQuotient + 2]
|
|
ld b, a
|
|
ld hl, wEnemyMonHP + 1
|
|
ld a, [hld]
|
|
ld e, a
|
|
ld a, [hl]
|
|
ld d, a
|
|
ld a, d
|
|
sub b
|
|
ret nz
|
|
ld a, e
|
|
sub c
|
|
ret
|
|
|
|
AIUseXAttack:
|
|
ld b, $A
|
|
ld a, X_ATTACK
|
|
jr AIIncreaseStat
|
|
|
|
AIUseXDefend:
|
|
ld b, $B
|
|
ld a, X_DEFEND
|
|
jr AIIncreaseStat
|
|
|
|
AIUseXSpeed:
|
|
ld b, $C
|
|
ld a, X_SPEED
|
|
jr AIIncreaseStat
|
|
|
|
AIUseXSpecial:
|
|
ld b, $D
|
|
ld a, X_SPECIAL
|
|
jr AIIncreaseStat ; this wasn't here before but it seems that this never actually happened??
|
|
;; fallthrough
|
|
|
|
AIIncreaseStat:
|
|
ld [wAIItem], a
|
|
push bc
|
|
call AIPrintItemUse_
|
|
pop bc
|
|
ld hl, wEnemyMoveEffect
|
|
ld a, [hld]
|
|
push af
|
|
ld a, [hl]
|
|
push af
|
|
push hl
|
|
ld a, XSTATITEM_DUPLICATE_ANIM
|
|
ld [hli], a
|
|
ld [hl], b
|
|
callfar StatModifierUpEffect
|
|
pop hl
|
|
pop af
|
|
ld [hli], a
|
|
pop af
|
|
ld [hl], a
|
|
jp DecrementAICount
|
|
|
|
AIPrintItemUse:
|
|
ld [wAIItem], a
|
|
call AIPrintItemUse_
|
|
jp DecrementAICount
|
|
|
|
AIPrintItemUse_:
|
|
; print "x used [wAIItem] on z!"
|
|
ld a, [wAIItem]
|
|
ld [wd11e], a
|
|
call GetItemName
|
|
ld hl, AIBattleUseItemText
|
|
jp PrintText
|
|
|
|
AIBattleUseItemText:
|
|
text_far _AIBattleUseItemText
|
|
text_end
|