-
Notifications
You must be signed in to change notification settings - Fork 93
Choices Within Attacks
In this tutorial, we will learn how to create something with nearly infinite potential: the ability to select an attack, and then select one of two options which alter that attack. This is useful for making attacks which require more thinking than usual, as well as making them more exciting in general.
For this tutorial's example, we will refer to Flareon's Flare Blitz attack in Pokemon TCG Neo, as it is a simple example. This attack allows the player to choose to use the attack with no effect or to have the Attacking Pokémon do 30 more damage to the Defending Pokémon and then do 30 damage to itself. This means that Flareon's Flare Blitz is capable of either doing 30 damage, or 60 damage but with 30 recoil.
- First, we will be making a text definition. (check here for a tutorial on adding new texts):
FlareBlitzYesNoText:
text "Do 30 more damage, but Recoil?"
line " Yes No"
done
This is the text that will show up on the attack menu after the player selects Flare Blitz. The yes and no options are spaced exactly where the cursors will be during the selection process.
- Next, we will put the effect commands in src/engine/duel/effect_commands.asm. You can of course rename then to whatever you want, but in this example, because Flareon is the only Pokémon in Neo that uses this particular modal option, the effect functions are named after it.
; Yes/No: Do 30 more damage in exchange for 30 recoil damage
CanDo30ButRecoilEffectCommands:
dbw EFFECTCMDTYPE_BEFORE_DAMAGE, FlareonDamageEffect
dbw EFFECTCMDTYPE_REQUIRE_SELECTION, PlayerYesNoFlareonEffect
dbw EFFECTCMDTYPE_AFTER_DAMAGE, FlareonRecoilEffect
dbw EFFECTCMDTYPE_AI_SELECTION, FlareonFB_AISelectEffect
dbw EFFECTCMDTYPE_AI, FlareonFB_AIEffect
db $00
- Now, we will go into src/engine/duel/effect_functions.asm and create the effect functions for the player, which are the first three in the above effect commands.
; output:
; [hTemp_ffa0] = whichever option the Player selected (0 = "Yes", 1 = "No")
PlayerYesNoFlareonEffect:
bank1call DrawDuelMainScene ; draws a screen for the player to select from
ldtx hl, FlareonYesNoText ; loads the text we made in step 1
call TwoItemHorizontalMenu ; defines that this text contains 2 menu items (yes/no)
ldh a, [hKeysHeld] ; loads the player's input
and B_BUTTON
jr nz, PlayerYesNoFlareonEffect ; this forces the player to select either "Yes" or "No", can't exit
ldh a, [hCurMenuItem] ; stores the result in a
ldh [hTemp_ffa0], a ; loads what the player selected into hTemp_ffa0
ret
; preserves all registers except af
; input:
; [hTemp_ffa0] != 0: immediately return without applying the effect
FlareonDamageEffect:
ldh a, [hTemp_ffa0]
or a
ret nz ; return if "Yes" wasn't selected
; otherwise, load the correct animation and increase the damage by 30
ld a, ATK_ANIM_FLARE_BLITZ
ld [wLoadedAttackAnimation], a
ld a, 30
jp AddToDamage
; input:
; [hTemp_ffa0] != 0: immediately return without applying the effect
FlareonRecoilEffect:
ldh a, [hTemp_ffa0]
or a
ret nz ; return if "Yes" wasn't selected
; otherwise, the Attacking Pokémon does 30 damage to itself
ld a, 30
jp DealRecoilDamageToSelf
That's it for the Player! But the AI still doesn't understand the effect. We will have to give the AI its own logic.
- How you do the AI logic will vary a lot depending on what the effect of your choice will be, and what you want the AI to prioritize. In this particular example, we will tell the AI to always select "Yes" if the Defending Pokémon's HP is above 30 and "No" if its HP is between 0 and 30. This is just a simple logic so that the AI will try to KO the Defending Pokémon as much as possible, but not resort to self damage if the base damage is enough to KO the Defending Pokémon. Again, it is possible in this example to have the AI always choose "Yes" even at the risk of self KO, or the opposite and always select "No".
Go back to src/engine/duel/effect_functions.asm
; preserves bc and hl
FlareonFB_AIEffect:
ld a, 30
lb de, 30, 60 ; The AI now knows it will do either 30 or 60 damage.
jp SetExpectedAIDamage
; preserves bc and de
; output:
; [hTemp_ffa0] = whichever option the AI selected (0 = "Yes", 1 = "No")
FlareonFB_AISelectEffect:
ld a, DUELVARS_ARENA_CARD_HP
call GetNonTurnDuelistVariable
; a = Defending Pokémon's current HP
cp 31
jr nc, .more_than_30_hp
; base damage can already KO
ld a, 1 ; "No"
ldh [hTemp_ffa0], a
ret
.more_than_30_hp
xor a ; "Yes"
ldh [hTemp_ffa0], a
ret
And now the AI understands the attack! Of course, you can program more logic than this, but in this tutorial, the above will suffice.