Skip to content

Update the confusion mechanic

ElectroDeoxys edited this page May 13, 2024 · 1 revision

The confusion mechanics have changed in the TCG, as confusion no longer puts any restriction on retreating, plus confusion damage dealt to the card is increased from 20 to 30, and no weakness and resistance is applied.

Contents

  1. Remove retreat coin toss
  2. Deal 30 damage instead of 20
  3. Remove useless stuff
  4. Additional considerations

1. Remove retreat coin toss

The first thing to do is remove all logic pertaining to retreating while confused. Edit src/engine/duel/core.asm:

 ; triggered by selecting the "Retreat" item in the duel menu
 DuelMenu_Retreat:
-       ld a, DUELVARS_ARENA_CARD_STATUS
-       call GetTurnDuelistVariable
-       and CNF_SLP_PRZ
-       cp CONFUSED
-       ldh [hTemp_ffa0], a
-       jr nz, .not_confused
-       ld a, [wGotHeadsFromConfusionCheckDuringRetreat]
-       or a
-       jr nz, .unable_due_to_confusion
-       call CheckAbleToRetreat
-       jr c, .unable_to_retreat
-       call DisplayRetreatScreen
-       jr c, .done
-       ldtx hl, SelectPkmnOnBenchToSwitchWithActiveText
-       call DrawWideTextBox_WaitForInput
-       call OpenPlayAreaScreenForSelection
-       jr c, .done
-       ld [wBenchSelectedPokemon], a
-       ld a, [wBenchSelectedPokemon] ; unnecessary
-       ldh [hTempPlayAreaLocation_ffa1], a
-       ld a, OPPACTION_ATTEMPT_RETREAT
-       call SetOppAction_SerialSendDuelData
-       call AttemptRetreat
-       jr nc, .done
-       call DrawDuelMainScene
-
-.unable_due_to_confusion
-       ldtx hl, UnableToRetreatText
-       call DrawWideTextBox_WaitForInput
-       jp PrintDuelMenuAndHandleInput
-
-.not_confused
        ; note that the energy cards are discarded (DiscardRetreatCostCards), then returned
        ; (ReturnRetreatCostCardsToArena), then discarded again for good (AttemptRetreat).
        ; It's done this way so that the retreating Pokemon is listed with its energies updated
-       ; when the Play Area screen is shown to select the Pokemon to switch to. The reason why
-       ; AttemptRetreat is responsible for discarding the energy cards is because, if the
-       ; Pokemon is confused, it may not be able to retreat, so they cannot be discarded earlier.
+       ; when the Play Area screen is shown to select the Pokemon to switch to.
        call CheckAbleToRetreat
        jr c, .unable_to_retreat
        call DisplayRetreatScreen

Here we deleted the functionality of checking for confusion when the player retreats, and instead jumps straight to code that would run if the card was otherwise not confused. Next we change the AttemptRetreat routine in the same file:

-; discard retreat cost energy cards and attempt retreat of the arena card.
-; return carry if unable to retreat this turn due to unsuccessful confusion check
+; discard retreat cost energy cards and retreat the arena card.
 ; if successful, the retreated card is replaced with a bench Pokemon card
 AttemptRetreat:
        call DiscardRetreatCostCards
-       ldh a, [hTemp_ffa0]
-       and CNF_SLP_PRZ
-       cp CONFUSED
-       jr nz, .success
-       ldtx de, ConfusionCheckRetreatText
-       call TossCoin
-       jr c, .success
-       ld a, 1
-       ld [wGotHeadsFromConfusionCheckDuringRetreat], a
-       scf
-       ret
-.success
        ldh a, [hTempPlayAreaLocation_ffa1]
        ld e, a
-       call SwapArenaWithBenchPokemon
-       xor a
-       ld [wGotHeadsFromConfusionCheckDuringRetreat], a
-       ret
+       jp SwapArenaWithBenchPokemon

The routine is greatly simplified, there's no more need to toss a coin to be successful in retreating, and so the swap is done directly.

2. Deal 30 damage instead of 20

Next we will do the necessary changes to deal exactly 30 damage to the card if it fails the confusion attack check. Edit src/home/duel.asm:

 ; called when attacker deals damage to itself due to confusion
-; display the corresponding animation and deal 20 damage to self
+; display the corresponding animation and deal 30 damage to self
 HandleConfusionDamageToSelf::
        bank1call DrawDuelMainScene
        ld a, 1
        ...
        call DrawWideTextBox_PrintText
        ld a, ATK_ANIM_CONFUSION_HIT
        ld [wLoadedAttackAnimation], a
-       ld a, 20 ; damage
+       ld a, 30 ; damage
        call DealConfusionDamageToSelf
        call Func_1bb4
        call Func_6e49
        ...
        push af
        ld a, [wTempTurnDuelistCardID]
        ld [wTempNonTurnDuelistCardID], a
-       bank1call ApplyDamageModifiers_DamageToSelf ; this is at bank 0
-       ld a, [wDamageEffectiveness]
+       xor a
+       ld [wDamageEffectiveness], a
+       ld hl, wDamage
+       ld e, [hl]
+       inc hl
+       ld d, [hl]
        ld c, a
        ld b, PLAY_AREA_ARENA
        ld a, DUELVARS_ARENA_CARD_HP

Firstly, we adjust the damage from 20 to 30. Secondly, we bypass the self damage routine and apply the damage directly without modifiers (like weakness/resitance and plusplower/defender). Thirdly, we guarantee that wDamageEffectiveness is zeroed so that the damage appears correctly when the animation is playing.

With this change, now the text shows the wrong information when dealing damage. Edit src/text/text1.asm and change the text from 20 to 30 damage:

 DamageToSelfDueToConfusionText:
-       text "20 damage to Self due to Confusion."
+       text "30 damage to Self due to Confusion."
        done

3. Remove useless stuff

There is some stuff that we can now remove completely to make space in the ROM. First we will delete the text that is printed in the confusion retreat check. Edit src/text/text_offsets.asm:

 TextOffsets::
        ...
        textpointer AcidCheckText                                      ; 0x00f5
        textpointer TransparencyCheckText                              ; 0x00f6
        textpointer ConfusionCheckDamageText                           ; 0x00f7
-       textpointer ConfusionCheckRetreatText                          ; 0x00f8
        textpointer PokemonsSleepCheckText                             ; 0x00f9
        textpointer PoisonedIfHeadsConfusedIfTailsText                 ; 0x00fa
        textpointer IfHeadsDoNotReceiveDamageOrEffectText              ; 0x00fb

Edit src/text/text2.asm:

 ConfusionCheckDamageText:
        line "If Tails, damage to yourself!"
        done

-ConfusionCheckRetreatText:
-       text "Confusion check!"
-       line "If Tails, unable to Retreat."
-       done
-
 PokemonsSleepCheckText:
        text "<RAMTEXT>'s Sleep check."
        done

Moreover, we can now remove the WRAM address that keeps track of whether the player got a heads in the retreat check or not. Edit src/wram.asm:

 wGotHeadsFromSandAttackOrSmokescreenCheck:: ; cc0a
 wAlreadyPlayedEnergy:: ; cc0b
        ds $1

-; set to 1 if the confusion check coin toss in AttemptRetreat is heads
-wGotHeadsFromConfusionCheckDuringRetreat:: ; cc0c
-       ds $1
-
 ; DUELIST_TYPE_* of the turn holder
 wDuelistType:: ; cc0d
        ds $1

Next we will remove all usages of this label. Edit src/engine/duel/core.asm again:

 InitVariablesToBeginTurn:
        xor a
        ld [wAlreadyPlayedEnergy], a
-       ld [wGotHeadsFromConfusionCheckDuringRetreat], a
        ld [wGotHeadsFromSandAttackOrSmokescreenCheck], a
        ldh a, [hWhoseTurn]
        ld [wWhoseTurn], a

Edit src/engine/duel/ai/retreat.asm:

 ; determine AI score for retreating
 ; return carry if AI decides to retreat
 AIDecideWhetherToRetreat:
-       ld a, [wGotHeadsFromConfusionCheckDuringRetreat]
-       or a
-       jp nz, .no_carry
        xor a
        ld [wAIPlayEnergyCardForRetreat], a
        call LoadDefendingPokemonColorWRAndPrizeCards

4. Additional considerations

Now the confusion mechanic works as expected. However, you will probably want to have the AI know how to play with these modified rules. Retreating while confused is now a much more viable option and attacking is a riskier gamble, so the AI should be encouraged to retreat in this situation. Or only consider switching if confusion damage is in KO range, etc. One easy modification to do is to slightly increase the score given when considering retreating in AIDecideWhetherToRetreat. Edit src/engine/duel/ai/retreat.asm:

 ; determine AI score for retreating
 ; return carry if AI decides to retreat
 AIDecideWhetherToRetreat:
        ...
        and CNF_SLP_PRZ
        cp CONFUSED
        jr nz, .check_ko_1
-       ld a, 1
+       ld a, 3
        call AddToAIScore

 .check_ko_1

This will make it more likely for the AI to switch when having a confused Arena card. You should test around to see what might work for the AI.