summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/engine/bank05.asm605
-rw-r--r--src/wram.asm30
2 files changed, 627 insertions, 8 deletions
diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm
index 464ce48..e643a3e 100644
--- a/src/engine/bank05.asm
+++ b/src/engine/bank05.asm
@@ -54,7 +54,66 @@ PointerTable_14000: ; 14000 (05:4000)
dw $48dc ; IMAKUNI_DECK
; 1406a
- INCROM $1406a, $14226
+PointerTable_1406a: ; 1406a (5:406a)
+ dw $406c
+ dw Func_14078
+ dw Func_14078
+ dw $409e
+ dw $40a2
+ dw $40a6
+ dw $40aa
+
+Func_14078: ; 14078 (5:4078)
+ call Func_15eae
+ call Func_158b2
+ jr nc, .asm_14091
+ call Func_15b72
+ call Func_15d4f
+ call Func_158b2
+ jr nc, .asm_14091
+ call Func_15b72
+ call Func_15d4f
+.asm_14091
+ call Func_164e8
+ call Func_169f8
+ ret c
+ ld a, $05
+ bank1call AIMakeDecision
+ ret
+; 0x1409e
+
+ INCROM $1409e, $140ae
+
+; returns carry if damage dealt from any of
+; a card's moves knocks out defending Pokémon
+; input:
+; hTempPlayAreaLocation_ff9d = location of attacking card to consider
+CheckIfAnyMoveKnocksOutDefendingCard: ; 140ae (5:40ae)
+ xor a ; first move
+ call CheckIfMoveKnocksOutDefendingCard
+ ret c
+ ld a, $01 ; second move
+; fallthrough
+
+CheckIfMoveKnocksOutDefendingCard: ; 140b5 (5:40b5)
+ call CalculateSelectedMoveDamageDoneToDefendingCard
+ ld a, DUELVARS_ARENA_CARD_HP
+ call GetNonTurnDuelistVariable
+ ld hl, wDamage
+ sub [hl]
+ ret c
+ ret nz
+ scf
+ ret
+; 0x140c5
+
+ INCROM $140c5, $140fe
+
+Func_140fe: ; 140fe (5:40fe)
+ INCROM $140fe, $1410a
+
+Func_1410a: ; 1410a (5:410a)
+ INCROM $1410a, $14226
Func_14226: ; 14226 (5:4226)
call CreateHandCardList
@@ -78,7 +137,225 @@ Func_14226: ; 14226 (5:4226)
jr .check_for_next_pokemon
; 0x1424b
- INCROM $1424b, $14663
+Func_1424b: ; 1424b (5:424b)
+ INCROM $1424b, $1433d
+
+Func_1433d: ; 1433d (5:433d)
+ INCROM $1433d, $143e5
+
+; stores in wDamage, wccbb and wccbc the calculated damage
+; done to the defending Pokémon by a given card and move
+; input:
+; a = move index to take into account
+; hTempPlayAreaLocation_ff9d = location of attacking card to consider
+CalculateSelectedMoveDamageDoneToDefendingCard: ; 143e5 (5:43e5)
+ ld [wSelectedMoveIndex], a
+ ld e, a
+ ldh a, [hTempPlayAreaLocation_ff9d]
+ add DUELVARS_ARENA_CARD
+ call GetTurnDuelistVariable
+ ld d, a
+ call CopyMoveDataAndDamage_FromDeckIndex
+ ld a, [wLoadedMoveCategory]
+ cp POKEMON_POWER
+ jr nz, .not_pokemon_power
+
+ ; set wDamage, wccbb and wccbc to zero
+ ld hl, wDamage
+ xor a
+ ld [hli], a
+ ld [hl], a
+ ld [wccbb], a
+ ld [wccbc], a
+ ld e, a
+ ld d, a
+ ret
+
+.not_pokemon_power
+ ; set wccbb and wccbc to damage of move
+ ld a, [wDamage]
+ ld [wccbb], a
+ ld [wccbc], a
+ ld a, $09
+ call TryExecuteEffectCommandFunction
+ ld a, [wccbb]
+ ld hl, wccbc
+ or [hl]
+ jr nz, .asm_1442a
+ ld a, [wDamage]
+ ld [wccbb], a
+ ld [wccbc], a
+.asm_1442a
+; if temp. location is active, damage calculation can be done...
+ ldh a, [hTempPlayAreaLocation_ff9d]
+ or a
+ jr z, CalculateDamageDoneToDefendingCard
+
+; ...otherwise substatuses need to be temporarily reset to account
+; for the switching, to obtain the right damage calculation...
+ ; reset substatus1
+ ld a, DUELVARS_ARENA_CARD_SUBSTATUS1
+ call GetTurnDuelistVariable
+ push af
+ push hl
+ ld [hl], $00
+ ; reset substatus2
+ ld l, DUELVARS_ARENA_CARD_SUBSTATUS2
+ ld a, [hl]
+ push af
+ push hl
+ ld [hl], $00
+ ; reset changed resistance
+ ld l, DUELVARS_ARENA_CARD_CHANGED_RESISTANCE
+ ld a, [hl]
+ push af
+ push hl
+ ld [hl], $00
+ call CalculateDamageDoneToDefendingCard
+; ...and subsequently recovered to continue the battle normally
+ pop hl
+ pop af
+ ld [hl], a
+ pop hl
+ pop af
+ ld [hl], a
+ pop hl
+ pop af
+ ld [hl], a
+ ret
+
+; calculates the damage that will be dealt to the player's active card
+; using the card that is located in hTempPlayAreaLocation_ff9d
+; taking into account weakness/resistance/pluspowers/defenders/etc
+; and outputs the result capped at a max of $ff
+; input:
+; wccbb -> base damage
+; wccbc -> base damage
+; wDamage -> base damage
+; hTempPlayAreaLocation_ff9d = turn holder's card location as the attacker
+CalculateDamageDoneToDefendingCard: ; 14453 (5:4453)
+ ld hl, wccbb
+ call _CalculateDamageDoneToDefendingCard
+ ld hl, wccbc
+ call _CalculateDamageDoneToDefendingCard
+ ld hl, wDamage
+; fallthrough
+
+_CalculateDamageDoneToDefendingCard: ; 14462 (5:4462)
+ ld e, [hl]
+ ld d, $00
+ push hl
+
+ ; load this card's data
+ ldh a, [hTempPlayAreaLocation_ff9d]
+ add DUELVARS_ARENA_CARD
+ call GetTurnDuelistVariable
+ call LoadCardDataToBuffer2_FromDeckIndex
+ ld a, [wLoadedCard2ID]
+ ld [wTempTurnDuelistCardID], a
+
+ ; load player's arena card data
+ call SwapTurn
+ ld a, DUELVARS_ARENA_CARD
+ call GetTurnDuelistVariable
+ call LoadCardDataToBuffer2_FromDeckIndex
+ ld a, [wLoadedCard2ID]
+ ld [wTempNonTurnDuelistCardID], a
+ call SwapTurn
+
+ push de
+ call HandleNoDamageOrEffectSubstatus
+ pop de
+ jr nc, .vulnerable
+ ; invulnerable to damage
+ ld de, $0
+ jr .done
+.vulnerable
+ ldh a, [hTempPlayAreaLocation_ff9d]
+ or a
+ call z, HandleDoubleDamageSubstatus
+ ; skips the weak/res checks if bit 7 is set
+ ; I guess to avoid overflowing?
+ ; should probably just have skipped weakness test instead?
+ bit 7, d
+ res 7, d
+ jr nz, .not_resistant
+
+ ; figure out if player's card is weak to this card
+ ldh a, [hTempPlayAreaLocation_ff9d]
+ call GetPlayAreaCardColor
+ call TranslateColorToWR
+ ld b, a
+ call SwapTurn
+ call GetArenaCardWeakness
+ call SwapTurn
+ and b
+ jr z, .not_weak
+ ; double de
+ sla e
+ rl d
+
+.not_weak
+ ; figure out if player's card is resists this card
+ call SwapTurn
+ call GetArenaCardResistance
+ call SwapTurn
+ and b
+ jr z, .not_resistant
+ ; subtract 30 from de
+ ld hl, $ffe2 ; $10000 - 30
+ add hl, de
+ ld e, l
+ ld d, h
+
+.not_resistant
+ ; apply pluspower and defender boosts
+ ldh a, [hTempPlayAreaLocation_ff9d]
+ add CARD_LOCATION_ARENA
+ ld b, a
+ call ApplyAttachedPluspower
+ call SwapTurn
+ ld b, CARD_LOCATION_ARENA
+ call ApplyAttachedDefender
+ call HandleDamageReduction
+ ; test if de underflowed
+ bit 7, d
+ jr z, .no_underflow
+ ld de, $0
+
+.no_underflow
+ ld a, DUELVARS_ARENA_CARD_STATUS
+ call GetTurnDuelistVariable
+ and DOUBLE_POISONED
+ jr z, .not_poisoned
+ ld c, 20
+ and $40 ; DOUBLE_POISONED - POISONED
+ jr nz, .add_poison
+ ld c, 10
+.add_poison
+ ld a, c
+ add e
+ ld e, a
+ ld a, $00
+ adc d
+ ld d, a
+.not_poisoned
+ call SwapTurn
+
+.done
+ pop hl
+ ld [hl], e
+ ld a, d
+ or a
+ ret z
+ ; cap damage
+ ld a, $ff
+ ld [hl], a
+ ret
+; 0x1450b
+
+Func_1450b ; 1450b (5:450b)
+ INCROM $1450b, $14663
Func_14663: ; 14663 (5:4663)
farcall Func_200e5
@@ -218,11 +495,30 @@ Func_1468b: ; 1468b (5:468b)
call $69f8
ret c
ld a, $5
- bank1call $67be
+ bank1call AIMakeDecision
ret
; 0x14786
- INCROM $14786, $15636
+ INCROM $14786, $1514f
+
+; these seem to be lists of card IDs
+; for the AI to look up in their hand
+Data_1514f: ; 1514f (5:514f)
+ db KANGASKHAN
+ db CHANSEY
+ db SNORLAX
+ db MR_MIME
+ db ABRA
+ db $00
+
+ db ABRA
+ db MR_MIME
+ db KANGASKHAN
+ db SNORLAX
+ db CHANSEY
+ db $00
+
+ INCROM $1515b, $15636
Func_15636: ; 15636 (5:5636)
ld a, $10
@@ -320,4 +616,303 @@ ZeroData: ; 1575e (5:575e)
ret
; 0x1576b
- INCROM $1576b, $18000
+ INCROM $1576b, $158b2
+
+Func_158b2 ; 158b2 (5:58b2)
+ INCROM $158b2, $15b72
+
+Func_15b72 ; 15b72 (5:5b72)
+ INCROM $15b72, $15d4f
+
+Func_15d4f ; 15d4f (5:5d4f)
+ INCROM $15d4f, $15ea6
+
+; Copy cards from wDuelTempList to wHandTempList
+CopyHandCardList: ; 15ea6 (5:5ea6)
+ ld a, [hli]
+ ld [de], a
+ cp $ff
+ ret z
+ inc de
+ jr CopyHandCardList
+
+Func_15eae: ; 15eae (5:5eae)
+ call CreateHandCardList
+ call SortTempDeckByIdList
+ ld hl, wDuelTempList
+ ld de, wHandTempList
+ call CopyHandCardList
+ ld hl, wHandTempList
+
+.next_card
+ ld a, [hli]
+ cp $ff
+ jp z, Func_15f4c
+
+ ld [wcdf3], a
+ push hl
+ call LoadCardDataToBuffer1_FromDeckIndex
+ ld a, [wLoadedCard1Type]
+ cp TYPE_ENERGY
+ jr nc, .skip
+ ; skip non-pokemon cards
+
+ ld a, [wLoadedCard1Stage]
+ or a
+ jr nz, .skip
+ ; skip non-basic pokemon
+
+ ld a, $82
+ ld [wcdbe], a
+ call Func_161d5
+ ld a, $ef
+ call GetTurnDuelistVariable
+ cp $04
+ jr c, .asm_15ef2
+ ld a, $14
+ call Func_1410a
+ jr .asm_15ef7
+.asm_15ef2
+ ld a, $32
+ call Func_140fe
+.asm_15ef7
+ xor a
+ ldh [hTempPlayAreaLocation_ff9d], a
+ call Func_173b1
+ jr nc, .asm_15f04
+ ld a, $14
+ call Func_140fe
+.asm_15f04
+ ld a, [wcdf3]
+ call Func_163c9
+ call Func_1637b
+ jr nc, .asm_15f14
+ ld a, $14
+ call Func_140fe
+.asm_15f14
+ ld a, [wcdf3]
+ call Func_16422
+ jr nc, .asm_15f21
+ ld a, $14
+ call Func_140fe
+.asm_15f21
+ ld a, [wcdf3]
+ call Func_16451
+ jr nc, .asm_15f2e
+ ld a, $0a
+ call Func_140fe
+.asm_15f2e
+ ld a, [wcdbe]
+ cp $b4
+ jr c, .skip
+ ld a, [wcdf3]
+ ldh [hTemp_ffa0], a
+ call Func_1433d
+ jr c, .skip
+ ld a, $01
+ bank1call AIMakeDecision
+ jr c, .done
+.skip
+ pop hl
+ jp .next_card
+.done
+ pop hl
+ ret
+
+Func_15f4c ; 15f4c (5:5f4c)
+ INCROM $15f4c, $161d5
+
+Func_161d5: ; 161d5 (5:61d5)
+; check if deck applies
+ ld a, [wOpponentDeckID]
+ cp LEGENDARY_ZAPDOS_DECK_ID
+ jr z, .begin
+ cp LEGENDARY_ARTICUNO_DECK_ID
+ jr z, .begin
+ cp LEGENDARY_RONALD_DECK_ID
+ jr z, .begin
+ ret
+
+; check if card applies
+.begin
+ ld a, [wLoadedCard1ID]
+ cp ARTICUNO2
+ jr z, .articuno
+ cp MOLTRES2
+ jr z, .moltres
+ cp ZAPDOS3
+ jr z, .zapdos
+ ret
+
+.articuno
+ ; exit if not enough Pokemon in Play Area
+ ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
+ call GetTurnDuelistVariable
+ cp 2
+ ret c
+
+ call Func_1628f
+ jr c, .asm_16258
+ call Func_162a1
+ jr nc, .asm_16258
+ call Func_158b2
+ jr c, .asm_16258
+
+ ; checks for player's active card status
+ ld a, DUELVARS_ARENA_CARD_STATUS
+ call GetNonTurnDuelistVariable
+ and CNF_SLP_PRZ
+ or a
+ jr nz, .asm_16258
+
+ ; checks for player's Pokemon Power
+ call SwapTurn
+ ld a, DUELVARS_ARENA_CARD
+ call GetTurnDuelistVariable
+ ld d, a
+ ld e, $00
+ call CopyMoveDataAndDamage_FromDeckIndex
+ call SwapTurn
+ ld a, [wLoadedMoveCategory]
+ cp POKEMON_POWER
+ jr z, .check_muk_and_snorlax
+
+ ; return if no space on the bench
+ ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
+ call GetTurnDuelistVariable
+ cp MAX_BENCH_POKEMON
+ jr c, .check_muk_and_snorlax
+ ret
+
+.check_muk_and_snorlax
+ ; checks for Muk in both Play Areas
+ ld a, MUK
+ call CountPokemonIDInBothPlayAreas
+ jr c, .asm_16258
+ ; checks if player's active card is Snorlax
+ ld a, DUELVARS_ARENA_CARD
+ call GetNonTurnDuelistVariable
+ call SwapTurn
+ call GetCardIDFromDeckIndex
+ call SwapTurn
+ ld a, e
+ cp SNORLAX
+ jr z, .asm_16258
+
+ ld a, $46
+ call Func_140fe
+ ret
+.asm_16258
+ ld a, $64
+ call Func_1410a
+ ret
+
+.moltres
+ ; checks if there's enough cards in deck
+ ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK
+ call GetTurnDuelistVariable
+ cp $38 ; max number of cards not in deck to activate
+ jr nc, .asm_16258
+ ret
+
+.zapdos
+ ; checks for Muk in both Play Areas
+ ld a, MUK
+ call CountPokemonIDInBothPlayAreas
+ jr c, .asm_16258
+ ret
+; 0x16270
+
+ INCROM $16270, $1628f
+
+Func_1628f: ; 1628f (5:628f)
+ xor a
+ ldh [hTempPlayAreaLocation_ff9d], a
+ call CheckIfAnyMoveKnocksOutDefendingCard
+ jr nc, .asm_1629f
+ call Func_1424b
+ jp c, .asm_1629f
+ scf
+ ret
+.asm_1629f
+ or a
+ ret
+; 0x162a1
+
+Func_162a1 ; 162a1 (5:62a1)
+ INCROM $162a1, $1633f
+
+; Goes through $00 terminated list pointed
+; by wcdae and compares it to each card in hand.
+; Sorts the hand in wDuelTempList so that the found card IDs
+; are in the same order as the list pointed by de.
+SortTempDeckByIdList: ; 1633f (5:633f)
+ ld a, [wcdaf]
+ or a
+ ret z
+ ld d, a
+ ld a, [wcdae]
+ ld e, a
+ ld c, $00
+.next_id
+ ld a, [de]
+ or a
+ ret z
+ inc de
+ ld hl, wDuelTempList
+ ld b, $00
+ add hl, bc
+
+ ld b, a
+.next_card
+ ld a, [hl]
+ ldh [hTempCardIndex_ff98], a
+ cp $ff
+ jr z, .next_id
+ push bc
+ push de
+ call GetCardIDFromDeckIndex
+ ld a, e
+ pop de
+ pop bc
+ cp b
+ jr nz, .not_same
+
+; found
+ push bc
+ push hl
+ ld b, $00
+ ld hl, wDuelTempList
+ add hl, bc
+ ld b, [hl]
+ ldh a, [hTempCardIndex_ff98]
+ ld [hl], a
+ pop hl
+ ld [hl], b
+ pop bc
+ inc c
+.not_same
+ inc hl
+ jr .next_card
+; 0x1637b
+
+Func_1637b ; 1637b (5:637b)
+ INCROM $1637b, $163c9
+
+Func_163c9 ; 163c9 (5:63c9)
+ INCROM $163c9, $16422
+
+Func_16422 ; 16422 (5:6422)
+ INCROM $16422, $16451
+
+Func_16451 ; 16451 (5:6451)
+ INCROM $16451, $164e8
+
+Func_164e8 ; 164e8 (5:64e8)
+ INCROM $164e8, $169f8
+
+Func_169f8 ; 169f8 (5:69f8)
+ INCROM $169f8, $173b1
+
+Func_173b1 ; 173b1 (5:73b1)
+ INCROM $173b1, $18000 \ No newline at end of file
diff --git a/src/wram.asm b/src/wram.asm
index 4210cf7..00beec2 100644
--- a/src/wram.asm
+++ b/src/wram.asm
@@ -1176,7 +1176,20 @@ wcda6:: ; cda6
wcda7:: ; cda7
ds $1
- ds $33
+ ds $6
+
+; pointer to a list of card IDs for sorting AI hand
+wcdae:: ; cdae
+ ds $1
+wcdaf:: ; cdaf
+ ds $1
+
+ ds $e
+
+wcdbe:: ; cdbe
+ ds $1
+
+ ds $1c
wcddb:: ; cddb
ds $1
@@ -1184,7 +1197,12 @@ wcddb:: ; cddb
wcddc:: ; cddc
ds $1
- ds $26
+ ds $16
+
+wcdf3:: ; cdf3
+ ds $1
+
+ ds $f
wce03:: ; ce03
ds $1
@@ -1475,7 +1493,13 @@ wcecc:: ; cecc
wcece:: ; cece
ds $2
- ds $47
+ ds $a
+
+; pointer to memory to store AI temporary hand card list
+wHandTempList:: ; ceda
+ ds $2
+
+ ds $3b
; used in bank2, probably related to wTempHandCardList (another temp list?)
wcf17:: ; cf17