Skip to content

BattleMod

src.templates.battle.BattleMod

Bases: BaseTemplate

  • A template modifier for Battle cards introduced in March of the Machine.
Adds
  • Defense text in bottom right of the card.
  • Flipside Power/Toughness text if reverse side is a creature.
  • Might add support for Transform icon in the future, if other symbols are used.
Source code in src\templates\battle.py
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
class BattleMod (BaseTemplate):
    """
    * A template modifier for Battle cards introduced in March of the Machine.

    Adds:
        * Defense text in bottom right of the card.
        * Flipside Power/Toughness text if reverse side is a creature.
        * Might add support for Transform icon in the future, if other symbols are used.
    """

    def __init__(self, layout: BattleLayout, **kwargs):
        super().__init__(layout, **kwargs)

    """
    * Layout Check
    """

    @auto_prop_cached
    def is_layout_battle(self) -> bool:
        """bool: Checks if this card matches BattleLayout."""
        return isinstance(self.layout, BattleLayout)

    """
    * Mixin Methods
    """

    @auto_prop_cached
    def text_layer_methods(self) -> list[Callable]:
        """Add Class text layers."""
        funcs = [self.text_layers_battle] if self.is_layout_battle else []
        return [*super().text_layer_methods, *funcs]

    @auto_prop_cached
    def post_text_methods(self) -> list[Callable]:
        """Rotate card sideways."""
        funcs = [psd.rotate_counter_clockwise] if self.is_layout_battle else []
        return [*super().post_text_methods, *funcs]

    """
    * Text Layers
    """

    @auto_prop_cached
    def text_layer_name(self) -> Optional[ArtLayer]:
        """Doesn't need to be shifted."""
        return psd.getLayer(LAYERS.NAME, self.text_group)

    @auto_prop_cached
    def text_layer_rules(self) -> Optional[ArtLayer]:
        """Supports noncreature and creature, with or without flipside PT."""
        if self.is_transform and self.is_front and self.is_flipside_creature:
            return psd.getLayer(LAYERS.RULES_TEXT_FLIP, self.text_group)
        return psd.getLayer(LAYERS.RULES_TEXT, self.text_group)

    @auto_prop_cached
    def text_layer_flipside_pt(self) -> Optional[ArtLayer]:
        """Flipside power/toughness layer for front face Transform cards."""
        return psd.getLayer(LAYERS.FLIPSIDE_POWER_TOUGHNESS, self.text_group)

    @auto_prop_cached
    def text_layer_defense(self) -> Optional[ArtLayer]:
        """Battle defense number in bottom right corner."""
        return psd.getLayer(LAYERS.DEFENSE, self.text_group)

    """
    * References
    """

    @auto_prop_cached
    def defense_reference(self) -> Optional[ArtLayer]:
        """Optional[ArtLayer]: Reference used to detect collision with the PT box."""
        return psd.getLayer(
            f"{LAYERS.DEFENSE_REFERENCE} Flip" if self.is_flipside_creature else LAYERS.DEFENSE_REFERENCE,
            self.text_group)

    """
    * Methods
    """

    def rules_text_and_pt_layers(self) -> None:
        """Overwrite rules text to enforce vertical text nudge with defense shield collision."""

        # Call super instead if not a Battle type card
        if not self.is_layout_battle:
            return super().rules_text_and_pt_layers()

        # Rules Text and Power / Toughness
        self.text.extend([
            FormattedTextArea(
                layer = self.text_layer_rules,
                contents = self.layout.oracle_text,
                flavor = self.layout.flavor_text,
                reference = self.textbox_reference,
                divider = self.divider_layer,
                pt_reference = self.defense_reference,
                centered = self.is_centered
            )])

    """
    * Battle Methods
    """

    def text_layers_battle(self) -> None:
        """Add and modify text layers required by Battle cards."""

        # Add defense text
        self.text.append(
            TextField(
                layer=self.text_layer_defense,
                contents=self.layout.defense))

        # Add flipside Power/Toughness
        if self.is_flipside_creature:
            self.text.append(
                TextField(
                    layer=self.text_layer_flipside_pt,
                    contents=str(self.layout.other_face_power) + "/" + str(self.layout.other_face_toughness)
                )
            )

Functions

defense_reference() -> Optional[ArtLayer]

Optional[ArtLayer]: Reference used to detect collision with the PT box.

Source code in src\templates\battle.py
 95
 96
 97
 98
 99
100
@auto_prop_cached
def defense_reference(self) -> Optional[ArtLayer]:
    """Optional[ArtLayer]: Reference used to detect collision with the PT box."""
    return psd.getLayer(
        f"{LAYERS.DEFENSE_REFERENCE} Flip" if self.is_flipside_creature else LAYERS.DEFENSE_REFERENCE,
        self.text_group)

is_layout_battle() -> bool

Source code in src\templates\battle.py
44
45
46
47
@auto_prop_cached
def is_layout_battle(self) -> bool:
    """bool: Checks if this card matches BattleLayout."""
    return isinstance(self.layout, BattleLayout)

post_text_methods() -> list[Callable]

Rotate card sideways.

Source code in src\templates\battle.py
59
60
61
62
63
@auto_prop_cached
def post_text_methods(self) -> list[Callable]:
    """Rotate card sideways."""
    funcs = [psd.rotate_counter_clockwise] if self.is_layout_battle else []
    return [*super().post_text_methods, *funcs]

rules_text_and_pt_layers() -> None

Overwrite rules text to enforce vertical text nudge with defense shield collision.

Source code in src\templates\battle.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def rules_text_and_pt_layers(self) -> None:
    """Overwrite rules text to enforce vertical text nudge with defense shield collision."""

    # Call super instead if not a Battle type card
    if not self.is_layout_battle:
        return super().rules_text_and_pt_layers()

    # Rules Text and Power / Toughness
    self.text.extend([
        FormattedTextArea(
            layer = self.text_layer_rules,
            contents = self.layout.oracle_text,
            flavor = self.layout.flavor_text,
            reference = self.textbox_reference,
            divider = self.divider_layer,
            pt_reference = self.defense_reference,
            centered = self.is_centered
        )])

text_layer_defense() -> Optional[ArtLayer]

Battle defense number in bottom right corner.

Source code in src\templates\battle.py
86
87
88
89
@auto_prop_cached
def text_layer_defense(self) -> Optional[ArtLayer]:
    """Battle defense number in bottom right corner."""
    return psd.getLayer(LAYERS.DEFENSE, self.text_group)

text_layer_flipside_pt() -> Optional[ArtLayer]

Flipside power/toughness layer for front face Transform cards.

Source code in src\templates\battle.py
81
82
83
84
@auto_prop_cached
def text_layer_flipside_pt(self) -> Optional[ArtLayer]:
    """Flipside power/toughness layer for front face Transform cards."""
    return psd.getLayer(LAYERS.FLIPSIDE_POWER_TOUGHNESS, self.text_group)

text_layer_methods() -> list[Callable]

Add Class text layers.

Source code in src\templates\battle.py
53
54
55
56
57
@auto_prop_cached
def text_layer_methods(self) -> list[Callable]:
    """Add Class text layers."""
    funcs = [self.text_layers_battle] if self.is_layout_battle else []
    return [*super().text_layer_methods, *funcs]

text_layer_name() -> Optional[ArtLayer]

Doesn't need to be shifted.

Source code in src\templates\battle.py
69
70
71
72
@auto_prop_cached
def text_layer_name(self) -> Optional[ArtLayer]:
    """Doesn't need to be shifted."""
    return psd.getLayer(LAYERS.NAME, self.text_group)

text_layer_rules() -> Optional[ArtLayer]

Supports noncreature and creature, with or without flipside PT.

Source code in src\templates\battle.py
74
75
76
77
78
79
@auto_prop_cached
def text_layer_rules(self) -> Optional[ArtLayer]:
    """Supports noncreature and creature, with or without flipside PT."""
    if self.is_transform and self.is_front and self.is_flipside_creature:
        return psd.getLayer(LAYERS.RULES_TEXT_FLIP, self.text_group)
    return psd.getLayer(LAYERS.RULES_TEXT, self.text_group)

text_layers_battle() -> None

Add and modify text layers required by Battle cards.

Source code in src\templates\battle.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
def text_layers_battle(self) -> None:
    """Add and modify text layers required by Battle cards."""

    # Add defense text
    self.text.append(
        TextField(
            layer=self.text_layer_defense,
            contents=self.layout.defense))

    # Add flipside Power/Toughness
    if self.is_flipside_creature:
        self.text.append(
            TextField(
                layer=self.text_layer_flipside_pt,
                contents=str(self.layout.other_face_power) + "/" + str(self.layout.other_face_toughness)
            )
        )