-
Notifications
You must be signed in to change notification settings - Fork 93
Attack Damage Based on the Total Amount of Energy In Play
For this tutorial, we will create some effect functions that do damage based on the total amount of Energy produced by all Energy cards in play. The first will be the more common function, dealing 10x damage for each Energy attached to 1 of the attacking player's Pokémon, while the second will do 10x damage for each Energy attached to any Pokémon in play (even the opponent's). The first effect is more common in the TCG, especially if you include all of the variants that only focus on 1 type of Energy (e.g. all Grass Energy), and it was first printed as the Magnetic Force attack on Magneton (Dragon #17). The second effect was only ever printed as the Psystorm attack, with the first instance being on Gardevoir ex (Sandstorm #96).
The effect commands for both of these attacks are rather simple, with one effect command to set the attack's damage and another to estimate the final damage so that the AI can decide whether or not it will use this attack. Because both wAIMinDamage and wAIMaxDamage in wram are set during the final call to SetDefiniteDamage
, the same effect function can be used for both commands.
Now, open src/engine/duel/effect_commands.asm, and add either or both of the following effects, depending on which attack(s) you are adding to the game. You can name the effect(s) whatever you wish, but make sure that you copy the correct label when you finally assign 1 of them to a Pokémon attack in src/data/cards.asm.
Damage10xEachEnergyInYourPlayArea:
dbw EFFECTCMDTYPE_BEFORE_DAMAGE, AllEnergyInYourPlayArea_10xDamageEffect
dbw EFFECTCMDTYPE_AI, AllEnergyInYourPlayArea_10xDamageEffect
db $00
Damage10xEachEnergyInBothPlayAreas:
dbw EFFECTCMDTYPE_BEFORE_DAMAGE, AllEnergyInBothPlayAreas_10xDamageEffect
dbw EFFECTCMDTYPE_AI, AllEnergyInBothPlayAreas_10xDamageEffect
db $00
All of the functions used for effect commands can be found in src/engine/duel/effect_functions.asm.
First, we will create a function that counts the total amount of Energy attached to all of the attacking player's Pokémon. We can call this routine from both of the effect functions we'll be creating afterward. We'll use the c, d, and e registers for our new function; although, hl will also be corrupted when we call GetTurnDuelistVariable
. The c register will be used as a counter to store all of the Energy that we find in the turn holder's play area;. Normally, the c register would initially be set to 0, but we'll skip that part so that we can call this function twice (once for each player) to gain the total amount of Energy attached to all Pokémon in both play areas. The d register will initially be set to the total number of Pokémon in the turn holder's play area; we can decrement that number each time we check a Pokémon, and when it reaches 0, we'll know that we can exit the play area loop and return. The e register will initially be set to the Active Pokémon's location (PLAY_AREA_ARENA, or 0); it's required for GetPlayAreaCardAttachedEnergies
, and each time we finish checking a location, we'll increase the value in e by 1 to move on to the next location on the Bench (PLAY_AREA_BENCH_*, or a number between 1 and 5).
; assumes the c register was set to 0 prior to this function being called.
; otherwise, it adds the amount of Energy found in the turn holder's play area to the value currently stored in c.
; preserves b
; output:
; c += total amount of Energy attached to all of the turn holder's Pokémon
; a = c
CountAllEnergyInTurnHolderPlayArea:
ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
call GetTurnDuelistVariable
ld d, a ; store the number of Pokémon in the turn holder's play area in the d register (this will let us know when we are done counting)
ld e, PLAY_AREA_ARENA ; store the first play area location to check in the e register
.loop_play_area
call GetPlayAreaCardAttachedEnergies
; a = [wTotalAttachedEnergies], or the total amount of Energy attached to the Pokémon in the location from e
add c ; add the Energy we just found to our counter in the c register
ld c, a ; and then update the counter
inc e ; move on to the next play area location
dec d ; decrease the number of Pokémon that we need to check by 1
jr nz, .loop_play_area ; only exit the loop if d = 0 (i.e. there are no more Pokémon to check), otherwise start over with the next Pokémon
ret
Note that you could also choose to count a specific type of Energy rather than all of them. All you would have to do is change a single line. For example, the following change would make the attack do 10x the total amount of Grass Energy attached to all of the turn holder's Pokémon.
call GetPlayAreaCardAttachedEnergies
- ; a = [wTotalAttachedEnergies], or the total amount of Energy attached to the Pokémon in the location from e
+ ld a, [wAttachedEnergies + GRASS]
add c ; add the Energy we just found to our counter in the c register
Now, let's create each of the effect functions that we referenced when making the effect commands. Both of the functions are very similar to one another, with the only difference being that the second one also adds in the opponent's Energy before setting the attack's damage.
; sets attack damage to 10x the total amount of Energy attached to all of the turn holder's Pokémon.
; preserves b
AllEnergyInYourPlayArea_10xDamageEffect:
ld c, 0 ; reset the Energy counter
call CountAllEnergyInTurnHolderPlayArea
call ATimes10 ; convert the Energy counter into a damage value by multiplying it by 10
jp SetDefiniteDamage ; and then store that damage value in various wram locations
; sets attack damage to 10x the total amount of Energy attached to all Pokémon in both play areas.
; preserves b
AllEnergyInBothPlayAreas_10xDamageEffect:
ld c, 0 ; reset the Energy counter
call SwapTurn
call CountAllEnergyInTurnHolderPlayArea
call SwapTurn
call CountAllEnergyInTurnHolderPlayArea
call ATimes10 ; convert the Energy counter into a damage value by multiplying it by 10
jp SetDefiniteDamage ; and then store that damage value in various wram locations