mirror of
https://github.com/magefree/mage.git
synced 2025-12-24 20:41:58 -08:00
Ready for Review: Implementing Battles (#10156)
* add types and subtypes * add startingDefense attribute * [MOM] Implement Invasion of Ravnica / Guildpact Paragon * fix two small errors * refactor various instances of "any target" * fully implement defense counters * battles can now be attacked * [MOM] Implement Invasion of Dominaria / Serra Faithkeeper * [MOM] Implement Invasion of Innistrad / Deluge of the Dead * [MOM] Implement Invasion of Kaladesh / Aetherwing, Golden-Scale Flagship * [MOM] Implement Invasion of Kamigawa / Rooftop Saboteurs * [MOM] Implement Invasion of Karsus / Refraction Elemental * [MOM] Implement Invasion of Tolvada / The Broken Sky * simplify battle info ability * fix verify failure * some more fixes for attacking battles * [MOM] Implement Invasion of Kaldheim / Pyre of the World Tree * [MOM] Implement Invasion of Lorwyn / Winnowing Forces * [MOM] Implement Invasion of Moag / Bloomwielder Dryads * [MOM] Implement Invasion of Shandalar / Leyline Surge * [MOM] Implement Invasion of Belenon / Belenon War Anthem * [MOM] Implement Invasion of Pyrulea / Gargantuan Slabhorn * [MOM] Implement Invasion of Vryn / Overloaded Mage-Ring * [MOM] Implement Marshal of Zhalfir * [MOM] Implement Sunfall * implement protectors for sieges * partially implement siege defeated trigger * fix verify failure * some updates to blocking * [MOM] Implement Invasion of Mercadia / Kyren Flamewright * [MOM] Implement Invasion of Theros / Ephara, Ever-Sheltering * [MOM] Implement Invasion of Ulgrotha / Grandmother Ravi Sengir * [MOM] Implement Invasion of Xerex / Vertex Paladin * add initial battle test * fix verify failure * [MOM] Implement Invasion of Amonkhet / Lazotep Convert * [MOM] update spoiler * update how protectors are chosen * update text * battles can't block * add control change test * rename battle test for duel * add multiplayer test * [MOM] Implement Invasion of Alara / Awaken the Maelstrom * [MOM] Implement Invasion of Eldraine * [MOM] Implement Invasion of Ergamon / Truga Cliffhanger * [MOM] Implement Invasion of Ixalan / Belligerent Regisaur * battles now cast transformed (this is super hacky but we need to refactor TDFCs anyway) * add TODO * add ignore for randomly failing test * a few small fixes * add defense to MtgJsonCard (unused like loyalty) * implement ProtectorIdPredicate * small fixes
This commit is contained in:
parent
edf1cff8a8
commit
947351932b
129 changed files with 4057 additions and 1087 deletions
|
|
@ -524,7 +524,13 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
|
|||
private final CardTypeCounter planeswalkerCounter = new CardTypeCounter() {
|
||||
@Override
|
||||
protected boolean is(CardView card) {
|
||||
return card.isPlanesWalker();
|
||||
return card.isPlaneswalker();
|
||||
}
|
||||
};
|
||||
private final CardTypeCounter battleCounter = new CardTypeCounter() {
|
||||
@Override
|
||||
protected boolean is(CardView card) {
|
||||
return card.isBattle();
|
||||
}
|
||||
};
|
||||
private final CardTypeCounter tribalCounter = new CardTypeCounter() {
|
||||
|
|
@ -542,6 +548,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
|
|||
instantCounter,
|
||||
planeswalkerCounter,
|
||||
sorceryCounter,
|
||||
battleCounter,
|
||||
tribalCounter
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ public class CardViewEDHPowerLevelComparator implements CardViewComparator {
|
|||
thisMaxPower = Math.max(thisMaxPower, 1);
|
||||
}
|
||||
|
||||
if (card.isPlanesWalker()) {
|
||||
if (card.isPlaneswalker()) {
|
||||
thisMaxPower = Math.max(thisMaxPower, 6);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -313,11 +313,15 @@ public final class GuiDisplayUtil {
|
|||
}
|
||||
buffer.append("</td></tr></table>");
|
||||
|
||||
String pt = "";
|
||||
String pt;
|
||||
if (card.isCreature()) {
|
||||
pt = card.getPower() + '/' + card.getToughness();
|
||||
} else if (card.isPlanesWalker()) {
|
||||
} else if (card.isPlaneswalker()) {
|
||||
pt = card.getLoyalty();
|
||||
} else if (card.isBattle()) {
|
||||
pt = card.getDefense();
|
||||
} else {
|
||||
pt = "";
|
||||
}
|
||||
|
||||
buffer.append("<table cellspacing=0 cellpadding=0 border=0 width='100%' valign='bottom'><tr><td><b>");
|
||||
|
|
|
|||
|
|
@ -797,8 +797,10 @@ public abstract class CardPanel extends MagePermanent implements ComponentListen
|
|||
}
|
||||
if (card.isCreature()) {
|
||||
sb.append('\n').append(card.getPower()).append('/').append(card.getToughness());
|
||||
} else if (card.isPlanesWalker()) {
|
||||
} else if (card.isPlaneswalker()) {
|
||||
sb.append('\n').append(card.getLoyalty());
|
||||
} else if (card.isBattle()) {
|
||||
sb.append('\n').append(card.getDefense());
|
||||
}
|
||||
if (card.getRules() == null) {
|
||||
card.overrideRules(new ArrayList<>());
|
||||
|
|
|
|||
|
|
@ -803,10 +803,14 @@ public class CardPanelRenderModeImage extends CardPanel {
|
|||
ptText1.setText(getGameCard().getPower());
|
||||
ptText2.setText("/");
|
||||
ptText3.setText(CardRendererUtils.getCardLifeWithDamage(getGameCard()));
|
||||
} else if (card.isPlanesWalker()) {
|
||||
} else if (card.isPlaneswalker()) {
|
||||
ptText1.setText("");
|
||||
ptText2.setText("");
|
||||
ptText3.setText(getGameCard().getLoyalty());
|
||||
} else if (card.isBattle()) {
|
||||
ptText1.setText("");
|
||||
ptText2.setText("");
|
||||
ptText3.setText(getGameCard().getDefense());
|
||||
} else {
|
||||
ptText1.setText("");
|
||||
ptText2.setText("");
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
|||
&& a.getPower().equals(b.getPower())
|
||||
&& a.getToughness().equals(b.getToughness())
|
||||
&& a.getLoyalty().equals(b.getLoyalty())
|
||||
&& a.getDefense().equals(b.getDefense())
|
||||
&& 0 == a.getColor().compareTo(b.getColor())
|
||||
&& a.getCardTypes().equals(b.getCardTypes())
|
||||
&& a.getSubTypes().equals(b.getSubTypes())
|
||||
|
|
@ -128,6 +129,7 @@ public class CardPanelRenderModeMTGO extends CardPanel {
|
|||
sb.append(this.view.getPower());
|
||||
sb.append(this.view.getToughness());
|
||||
sb.append(this.view.getLoyalty());
|
||||
sb.append(this.view.getDefense());
|
||||
sb.append(this.view.getColor().toString());
|
||||
sb.append(this.view.getType());
|
||||
sb.append(this.view.getExpansionSetCode());
|
||||
|
|
|
|||
|
|
@ -530,37 +530,37 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
g.setPaint(getSpiralLandTextboxColor(twoColors.get(0), twoColors.get(1), true));
|
||||
|
||||
// Horizontal bars
|
||||
g.fillRect(totalContentInset + 1 , typeLineY + boxHeight + 1 , contentWidth - 2 , height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 2*height_of_spiral, typeLineY + boxHeight + 1 + 2*height_of_spiral , contentWidth - 2 - 4*height_of_spiral , height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 4*height_of_spiral, typeLineY + boxHeight + 1 + 4*height_of_spiral , contentWidth - 2 - 8*height_of_spiral , height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 6*height_of_spiral, typeLineY + boxHeight + 1 + 6*height_of_spiral , contentWidth - 2 - 12*height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1, typeLineY + boxHeight + 1, contentWidth - 2, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 2 * height_of_spiral, typeLineY + boxHeight + 1 + 2 * height_of_spiral, contentWidth - 2 - 4 * height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 4 * height_of_spiral, typeLineY + boxHeight + 1 + 4 * height_of_spiral, contentWidth - 2 - 8 * height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 6 * height_of_spiral, typeLineY + boxHeight + 1 + 6 * height_of_spiral, contentWidth - 2 - 12 * height_of_spiral, height_of_spiral);
|
||||
|
||||
g.fillRect(totalContentInset + 1 + 6*height_of_spiral, typeLineY + boxHeight + 1 + total_height_of_box - 7*height_of_spiral, contentWidth - 2 - 12*height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 4*height_of_spiral, typeLineY + boxHeight + 1 + total_height_of_box - 5*height_of_spiral, contentWidth - 2 - 8*height_of_spiral , height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 2*height_of_spiral, typeLineY + boxHeight + 1 + total_height_of_box - 3*height_of_spiral, contentWidth - 2 - 4*height_of_spiral , height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 , typeLineY + boxHeight + 1 + total_height_of_box - height_of_spiral , contentWidth - 2 , height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 6 * height_of_spiral, typeLineY + boxHeight + 1 + total_height_of_box - 7 * height_of_spiral, contentWidth - 2 - 12 * height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 4 * height_of_spiral, typeLineY + boxHeight + 1 + total_height_of_box - 5 * height_of_spiral, contentWidth - 2 - 8 * height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 2 * height_of_spiral, typeLineY + boxHeight + 1 + total_height_of_box - 3 * height_of_spiral, contentWidth - 2 - 4 * height_of_spiral, height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1, typeLineY + boxHeight + 1 + total_height_of_box - height_of_spiral, contentWidth - 2, height_of_spiral);
|
||||
|
||||
// Vertical bars
|
||||
g.fillRect(totalContentInset + 1 , typeLineY + boxHeight + 1 , height_of_spiral, total_height_spiral - 1 );
|
||||
g.fillRect(totalContentInset + 1 + 2*height_of_spiral, typeLineY + boxHeight + 1 + 2*height_of_spiral, height_of_spiral, total_height_spiral - 1 - 4*height_of_spiral );
|
||||
g.fillRect(totalContentInset + 1 + 4*height_of_spiral, typeLineY + boxHeight + 1 + 4*height_of_spiral, height_of_spiral, total_height_spiral - 1 - 8*height_of_spiral );
|
||||
g.fillRect(totalContentInset + 1 + 6*height_of_spiral, typeLineY + boxHeight + 1 + 6*height_of_spiral, height_of_spiral, total_height_spiral - 1 - 12*height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1, typeLineY + boxHeight + 1, height_of_spiral, total_height_spiral - 1);
|
||||
g.fillRect(totalContentInset + 1 + 2 * height_of_spiral, typeLineY + boxHeight + 1 + 2 * height_of_spiral, height_of_spiral, total_height_spiral - 1 - 4 * height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 4 * height_of_spiral, typeLineY + boxHeight + 1 + 4 * height_of_spiral, height_of_spiral, total_height_spiral - 1 - 8 * height_of_spiral);
|
||||
g.fillRect(totalContentInset + 1 + 6 * height_of_spiral, typeLineY + boxHeight + 1 + 6 * height_of_spiral, height_of_spiral, total_height_spiral - 1 - 12 * height_of_spiral);
|
||||
|
||||
g.fillRect(totalContentInset + contentWidth - 7*height_of_spiral, typeLineY + boxHeight + 1 + 6*height_of_spiral, height_of_spiral, total_height_spiral - 1 - 12*height_of_spiral);
|
||||
g.fillRect(totalContentInset + contentWidth - 5*height_of_spiral, typeLineY + boxHeight + 1 + 4*height_of_spiral, height_of_spiral, total_height_spiral - 1 - 8*height_of_spiral );
|
||||
g.fillRect(totalContentInset + contentWidth - 3*height_of_spiral, typeLineY + boxHeight + 1 + 2*height_of_spiral, height_of_spiral, total_height_spiral - 1 - 4*height_of_spiral );
|
||||
g.fillRect(totalContentInset + contentWidth - 1*height_of_spiral, typeLineY + boxHeight + 1 + 0*height_of_spiral, height_of_spiral, total_height_spiral - 1 );
|
||||
g.fillRect(totalContentInset + contentWidth - 7 * height_of_spiral, typeLineY + boxHeight + 1 + 6 * height_of_spiral, height_of_spiral, total_height_spiral - 1 - 12 * height_of_spiral);
|
||||
g.fillRect(totalContentInset + contentWidth - 5 * height_of_spiral, typeLineY + boxHeight + 1 + 4 * height_of_spiral, height_of_spiral, total_height_spiral - 1 - 8 * height_of_spiral);
|
||||
g.fillRect(totalContentInset + contentWidth - 3 * height_of_spiral, typeLineY + boxHeight + 1 + 2 * height_of_spiral, height_of_spiral, total_height_spiral - 1 - 4 * height_of_spiral);
|
||||
g.fillRect(totalContentInset + contentWidth - 1 * height_of_spiral, typeLineY + boxHeight + 1 + 0 * height_of_spiral, height_of_spiral, total_height_spiral - 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.fillRect(
|
||||
totalContentInset + 1, typeLineY,
|
||||
contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1);
|
||||
totalContentInset + 1, typeLineY,
|
||||
contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a planeswalker, extend the textbox left border by some
|
||||
if (cardView.isPlanesWalker()) {
|
||||
if (cardView.isPlaneswalker()) {
|
||||
g.setPaint(borderPaint);
|
||||
g.fillRect(
|
||||
totalContentInset, typeLineY + boxHeight,
|
||||
|
|
@ -1116,7 +1116,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
|
||||
// Is it a walker? (But don't draw the box if it's a non-permanent view
|
||||
// of a walker without a starting loyalty (EG: Arlin Kord's flipped side).
|
||||
if (cardView.isPlanesWalker()
|
||||
if (cardView.isPlaneswalker()
|
||||
&& (cardView instanceof PermanentView || !cardView.getStartingLoyalty().equals("0"))) {
|
||||
// Draw the PW loyalty box
|
||||
int w = partBoxWidth;
|
||||
|
|
@ -1124,26 +1124,15 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
int x = cardWidth - partBoxWidth - borderWidth;
|
||||
int y = curY - h;
|
||||
|
||||
Polygon symbol = new Polygon(
|
||||
new int[]{
|
||||
x + w / 2,
|
||||
(int) (x + w * 0.9),
|
||||
x + w,
|
||||
(int) (x + w * 0.6),
|
||||
x + w / 2,
|
||||
(int) (x + w * 0.4),
|
||||
x,
|
||||
(int) (x + w * 0.1),},
|
||||
new int[]{
|
||||
y + h,
|
||||
(int) (y + 0.8 * h),
|
||||
y,
|
||||
(int) (y - 0.2 * h),
|
||||
y,
|
||||
(int) (y - 0.2 * h),
|
||||
y,
|
||||
(int) (y + 0.8 * h),},
|
||||
8);
|
||||
Polygon symbol = new Polygon();
|
||||
symbol.addPoint(x + w / 2, y + h);
|
||||
symbol.addPoint((int) (x + w * 0.9), (int) (y + 0.8 * h));
|
||||
symbol.addPoint(x + w, y);
|
||||
symbol.addPoint((int) (x + w * 0.6), (int) (y - 0.2 * h));
|
||||
symbol.addPoint(x + w / 2, y);
|
||||
symbol.addPoint((int) (x + w * 0.4), (int) (y - 0.2 * h));
|
||||
symbol.addPoint(x, y);
|
||||
symbol.addPoint((int) (x + w * 0.1), (int) (y + 0.8 * h));
|
||||
|
||||
// Draw + stroke
|
||||
g.setColor(Color.black);
|
||||
|
|
@ -1170,6 +1159,59 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
curY -= (int) (1.2 * y);
|
||||
}
|
||||
|
||||
// Is it a battle?
|
||||
if (cardView.isBattle()
|
||||
&& (cardView instanceof PermanentView || !cardView.getStartingDefense().equals("0"))) {
|
||||
// Draw the PW loyalty box
|
||||
int w = 3 * partBoxWidth / 4;
|
||||
int h = 3 * partBoxWidth / 4;
|
||||
int x = cardWidth - w - borderWidth;
|
||||
int y = curY - h;
|
||||
|
||||
Polygon symbol = new Polygon();
|
||||
symbol.addPoint(x + (0 * w) / 80, y + (2 * h) / 80);
|
||||
symbol.addPoint(x + (12 * w) / 80, y + (30 * h) / 80);
|
||||
symbol.addPoint(x + (3 * w) / 80, y + (40 * h) / 80);
|
||||
symbol.addPoint(x + (12 * w) / 80, y + (50 * h) / 80);
|
||||
symbol.addPoint(x + (0 * w) / 80, y + (78 * h) / 80);
|
||||
symbol.addPoint(x + (30 * w) / 80, y + (71 * h) / 80);
|
||||
symbol.addPoint(x + (40 * w) / 80, y + (80 * h) / 80);
|
||||
symbol.addPoint(x + (50 * w) / 80, y + (71 * h) / 80);
|
||||
symbol.addPoint(x + (80 * w) / 80, y + (78 * h) / 80);
|
||||
symbol.addPoint(x + (68 * w) / 80, y + (50 * h) / 80);
|
||||
symbol.addPoint(x + (77 * w) / 80, y + (40 * h) / 80);
|
||||
symbol.addPoint(x + (68 * w) / 80, y + (30 * h) / 80);
|
||||
symbol.addPoint(x + (80 * w) / 80, y + (2 * h) / 80);
|
||||
symbol.addPoint(x + (48 * w) / 80, y + (9 * h) / 80);
|
||||
symbol.addPoint(x + (40 * w) / 80, y + (0 * h) / 80);
|
||||
symbol.addPoint(x + (32 * w) / 80, y + (9 * h) / 80);
|
||||
|
||||
|
||||
// Draw + stroke
|
||||
g.setColor(Color.black);
|
||||
g.fillPolygon(symbol);
|
||||
g.setColor(new Color(200, 200, 200));
|
||||
g.setStroke(new BasicStroke(2));
|
||||
g.drawPolygon(symbol);
|
||||
g.setStroke(new BasicStroke(1));
|
||||
|
||||
// Loyalty number
|
||||
String defense;
|
||||
if (cardView instanceof PermanentView) {
|
||||
defense = cardView.getDefense();
|
||||
} else {
|
||||
defense = cardView.getStartingDefense();
|
||||
}
|
||||
|
||||
g.setFont(ptTextFont);
|
||||
g.setColor(Color.white);
|
||||
int defenseWidth = g.getFontMetrics().stringWidth(defense);
|
||||
g.drawString(defense, x + 1 + (w - defenseWidth) / 2, y - 1 + ptTextHeight + (h - ptTextHeight) / 2);
|
||||
|
||||
// Advance
|
||||
curY -= (int) (1.2 * y);
|
||||
}
|
||||
|
||||
// does it have damage on it?
|
||||
if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) {
|
||||
int x = cardWidth - partBoxWidth - borderWidth;
|
||||
|
|
@ -1769,7 +1811,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
|
||||
private static Color getLessOpaqueColor(Color color, boolean lessOpaqueRulesTextBox) {
|
||||
if (lessOpaqueRulesTextBox) {
|
||||
Color lessOpaque = new Color (color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha() - 50);
|
||||
Color lessOpaque = new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha() - 50);
|
||||
return lessOpaque;
|
||||
}
|
||||
return color;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue