diff options
-rw-r--r-- | src/engine/bank05.asm | 605 | ||||
-rw-r--r-- | src/wram.asm | 30 |
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 |