1
\$\begingroup\$

I am making a card game and I am having issues implementing "effects" and effects that are continuous.

How can I get effects to activate at the right times, before and after an attack does damage as well as apply a continuous effect through out each phase? Is there a way I can implement some sort of checklist system before and after attack?

I've tried 5 times with this, and this is just my latest attempt, How can I coded this system without making if-code mess. Any tips or help, would be greatly appreciate it! (as this is my first time making a trading card game.)

For context I am making this into a Discord bot!

What I need help with:

  • A System where I can check effects before, during and after attack
  • A system where I continuous effects are applied before during or after an attack
  • Applying the effect to the right target or to both targets
#while both players have health
# apply CONTINUOUS EFFECTS THROUGH OUT LOOP
while player1.hp > 0 and player2.hp > 0:
            print("test battle in progress")
            #class Card(object):
              #def __init__(self, name, hp, cardType, effect, attacks, description, ability):

            # Instantiate test subjects
            player1 = Card("Pinata Trent", 9, "Strong", None,
                       [Attack("Trample", 24, 2, None, None, None),
                        Attack("Body Bash", 62, 4, "selfDamage", 2, "self")],
                       "Trent card", None)

            player2 = Card("Barbarian", 10, "Strong", None,
                       [Attack("Head Bang", 68, 1, "selfDamage", 1, "self"),
                        Attack("Barbaric Swing ", 82, 2, None, None, None)],
                       None, None)


            #randomly choose a move for both NPC
            player1_move = random.choice(player1.attacks)
            player2_move = random.choice(player2.attacks)

            # Who ever player has the fastest attack value attacks first
            first_attack = firstAttack(player1_move, player2_move)

            if first_attack == 1:
                print("player 1 attacks first")
                await apply_damage(player2, player1_move)

                # Apply effect of attack after or before attack
                if player1_move.effect is not None:
                    print("player 1 attack effect activates")
                    player1 = player1.attack_effect(player1_move.effect, player1, player1_move.effectDamage)
                print(str(player1.hp) + " // " + str(player2.hp))

                # Player 2 attacks!
                if player2.hp > 0:

                    
                    player1.hp -= player2_move.damage
                    if player2_move.effect is not None:
                        print("player 2 attack effect activates")
                    player2 = player2.attack_effect(player2_move.effect, player2, player2_move.effectDamage)
                print(str(player1.hp) + " // " + str(player2.hp))
                await asyncio.sleep(2)

            elif first_attack == 2 and player2.hp > 0:
                print("player 2 attacks first")
                player1.hp -= player2_move.damage
                if player2_move.effect is not None:
                    print("player 2 attack effect activates")
                    player2 = player2.attack_effect(player2_move.effect, player2, player2_move.effectDamage)
                print(str(player1.hp) + " // " + str(player2.hp))

                # Player 1 attacks!
                if player1.hp > 0:
                    player2.hp -= player1_move.damage
                    if player1_move.effect is not None:
                        print("player 1 attack effect activates")
                        player1 = player1.attack_effect(player1_move.effect, player1, player1_move.effectDamage)
                print(str(player1.hp) + " // " + str(player2.hp))
                await asyncio.sleep(2)

attack move class:

class Attack:
    def __init__(self, name, speed, damage, effect, effectDamage, target):
        self.name = name
        self.speed = speed
        self.damage = damage
        self.effect = effect
        self.effectDamage = effectDamage
        self.target = target

    def attack_effect(self, tag, target, x):
        """
        todo: card attack effects
        """

        if tag == "selfDamage":
            target.hp -= x
            return target

        if tag == "forEachDamageMoreDamage":
            totalDamageTaken = target.starting_health - target.hp
            for i in target.attacks():
                if i.effect == "forEachDamageMoreDamage":
                    i.damage += totalDamageTaken
            return target

card class itself

class Card(object):
    def __init__(self, name, hp, cardType, effect, attacks, description, ability):
        self.name = name
        self.hp = hp
        self.starting_health = hp
        self.type = cardType
        self.attacks = attacks
        self.original_attacks = attacks
        self.effect = effect
        self.description = description

attack speed calculation

        def first_attack(player_atk_speed, opponent_atk_speed):
            if player_atk_speed.speed > opponent_atk_speed.speed:
                return 1
            elif player_atk_speed.speed < opponent_atk_speed.speed:
                return 2
            else:
                # decides who attacks based on random generation if attack speeds are EQUAL
                return random.randint(1, 2)
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

solved it, i made a method that i call for both players, and give it a tag that says when to activate, the method "Attack_effect_checker" will only do something if the attack itself has that same exact tag, "preAttack" or "postAttack"

    print(" -- pre damage phase --")

    # pre damage
    # player1 predamage check
    player_array = attack_effect_checker(player_array, 0, player_array[0].attacks[0], player_array[0].attacks[0].tag,
                                         "preAttack")
    # player2 predamage check
    player_array = attack_effect_checker(player_array, 1, player_array[1].attacks[0], player_array[1].attacks[0].tag,
                                         "preAttack")
    # post damage, after a player attacks, post attack effects trigger AND/OR continuous effects trigger
    print(" -- attack phase --")
    # player 2 attacks
    player_array[0].hp -= player_array[1].attacks[0].damage
    player_array = attack_effect_checker(player_array, 1, player_array[1].attacks[0], player_array[1].attacks[0].tag,
                                         "postAttack")
    # player 1 attacks
    player_array[1].hp -= apply_damage(player_array[1], player_array[0].attacks[0].damage)
    player_array = attack_effect_checker(player_array, 0, player_array[0].attacks[0], player_array[0].attacks[0].tag,
                                         "postAttack")

and attacks that have a "continuous" effect will apply during BOTH phases/turns

if selected_attack.trigger == phase or selected_attack.trigger == "continuous":
        if both_players[player_int].attacks[0].target == "self":
            both_players[player_int] = tag_apply(both_players[player_int], tag, selected_attack.effect_var, phase)
        elif both_players[player_int].attacks[0].target == "opponent":
            # if player_int 1 then select 0, elif 0 select 1, basically the opponent
            both_players[int(not player_int)] = tag_apply(both_players[int(not player_int)], tag,
                                                          selected_attack.effect_var, phase)
        else:
            print(" You really tried to target both of us huh")
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.