mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
new feature: Emblem Cards (#10498)
* new feature: Emblem Cards Allows match/tournament creator to specify cards to give each player emblem versions of (or just the starting player for symmetric effects). Technical details: - new UI for specifying emblem cards (.dck files) - available for all match/tournament types - new class `EmblemOfCard` - new method `copyWithZone` on `AbilityImpl` (used to make abilities work from command zone) - new fields on `GameOptions` and `MatchOptions` for emblem cards - emblems are granted after mulligans, before first turn (technically after Planechase starting plane creation) * fixes * defaults for emblem cards in match options (fixes quick game buttons) * minor fixes * use DeckCardInfo instead of Card for emblem cards options * restore accessible parent properties * fix images for card emblems * look up cards in a way that preserves which art * fix typos; make Emblem.sourceObject protected * add descriptions to planechase and emblem cards * fixes * add some unit tests for known working cards * fix author name * add explanation comment * fix up tests * copyWithZone: no longer modifies zone for singleton abilities * directly check for MageSingleton
This commit is contained in:
parent
04dba063aa
commit
41874b0b4b
15 changed files with 774 additions and 39 deletions
|
|
@ -22,11 +22,26 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jSeparator4" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="btnOK" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jSeparator3" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="txtEmblemCardsPerPlayer" max="32767" attributes="2"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnEmblemCardsPerPlayer" min="-2" pref="24" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="txtEmblemCardsStartingPlayer" max="32767" attributes="2"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnEmblemCardsStartingPlayer" min="-2" pref="24" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblMulliganType" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
|
@ -35,20 +50,21 @@
|
|||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblFreeMulligans" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnFreeMulligans" pref="126" max="32767" attributes="0"/>
|
||||
<Component id="spnFreeMulligans" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="chkPlaneChase" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblGeneralOptions" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblVariantOptions" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkPlaneChase" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkEmblemCards" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblEmblemCardsPerPlayer" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblEmblemCardsStartingPlayer" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblGeneralOptions" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="125" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="btnOK" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="planechaseDescriptionLabel" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="emblemCardsDescriptionLabel" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
|
@ -76,6 +92,28 @@
|
|||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="chkPlaneChase" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="planechaseDescriptionLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSeparator3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="chkEmblemCards" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="emblemCardsDescriptionLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblEmblemCardsPerPlayer" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtEmblemCardsPerPlayer" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnEmblemCardsPerPlayer" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblEmblemCardsStartingPlayer" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtEmblemCardsStartingPlayer" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnEmblemCardsStartingPlayer" alignment="3" min="-2" pref="21" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="jSeparator4" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="btnOK" min="-2" pref="30" max="-2" attributes="0"/>
|
||||
|
|
@ -173,7 +211,7 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkPlaneChase">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="PlaneChase"/>
|
||||
<Property name="text" type="java.lang.String" value="Planechase"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Use the PlaneChase variant for your game."/>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
|
|
@ -185,6 +223,19 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkPlaneChaseActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="planechaseDescriptionLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="<html>Shared planar deck of all implemented planes.<br>Uses a 9-sided planar die with 2 planeswalk sides and 2 chaos sides.<br>Some ability text may be incorrect.<br>Some rules details (such as who controls plane abilities) may be incorrect."/>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value="Planechase Description"/>
|
||||
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" value="Shared planar deck of all implemented planes.
Uses a 9-sided planar die with 2 planeswalk sides and 2 chaos sides.
Some ability text may be incorrect.
Some rules details (such as who controls plane abilities) may be incorrect."/>
|
||||
<Property name="AccessibleContext.accessibleParent" type="javax.accessibility.Accessible" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="chkPlaneChase"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator4">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnOK">
|
||||
|
|
@ -195,5 +246,80 @@
|
|||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOKActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator3">
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkEmblemCards">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="11" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Emblem Cards (Experimental)"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="If enabled, select cards to give players emblem copies of"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkEmblemCardsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnEmblemCardsPerPlayer">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="..."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnEmblemCardsPerPlayerActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtEmblemCardsPerPlayer">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtEmblemCardsPerPlayerActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblEmblemCardsPerPlayer">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Per-Player File"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="An emblem of each card in this file is given to each player"/>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleParent" type="javax.accessibility.Accessible" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="chkEmblemCards"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnEmblemCardsStartingPlayer">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="..."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnEmblemCardsStartingPlayerActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtEmblemCardsStartingPlayer">
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" value=""/>
|
||||
</AccessibilityProperties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtEmblemCardsStartingPlayerActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblEmblemCardsStartingPlayer">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Starting Player File"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="An emblem of every card in this file is given to the starting player (useful for symmetric effects)"/>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleParent" type="javax.accessibility.Accessible" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="chkEmblemCards"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="emblemCardsDescriptionLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="<html>Give players emblems with the abilities of cards.<br>Note that some abilities may not function correctly from the command zone.<br>If anything breaks, please report it on GitHub."/>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value="Emblem Cards description"/>
|
||||
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" value="Give players emblems with the abilities of cards.
Note that some abilities may not function correctly from the command zone.
If anything breaks, please report it on GitHub."/>
|
||||
</AccessibilityProperties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
package mage.client.dialog;
|
||||
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.cards.decks.DeckFileFilter;
|
||||
import mage.cards.decks.importer.DeckImporter;
|
||||
import mage.client.MageFrame;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.game.GameException;
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.game.mulligan.MulliganType;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* App GUI: custom options for match/tournament
|
||||
|
|
@ -19,28 +28,49 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
TABLE(
|
||||
PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS,
|
||||
PreferencesDialog.KEY_NEW_TABLE_MULLIGAN_TYPE,
|
||||
PreferencesDialog.KEY_NEW_TABLE_PLANECHASE
|
||||
PreferencesDialog.KEY_NEW_TABLE_PLANECHASE,
|
||||
PreferencesDialog.KEY_NEW_TABLE_EMBLEM_CARDS_ENABLED,
|
||||
PreferencesDialog.KEY_NEW_TABLE_EMBLEM_CARDS_PER_PLAYER_FILE,
|
||||
PreferencesDialog.KEY_NEW_TABLE_EMBLEM_CARDS_STARTING_PLAYER_FILE
|
||||
),
|
||||
|
||||
TOURNEY(
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS,
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_MULLIGUN_TYPE,
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_PLANE_CHASE
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_PLANE_CHASE,
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_EMBLEM_CARDS_ENABLED,
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_EMBLEM_CARDS_PER_PLAYER_FILE,
|
||||
PreferencesDialog.KEY_NEW_TOURNAMENT_EMBLEM_CARDS_STARTING_PLAYER_FILE
|
||||
);
|
||||
public final String NUMBER_OF_FREE_MULLIGANS;
|
||||
public final String MULLIGAN_TYPE;
|
||||
public final String PLANECHASE;
|
||||
public final String EMBLEM_CARDS_ENABLED;
|
||||
public final String EMBLEM_CARDS_PER_PLAYER_FILE;
|
||||
public final String EMBLEM_CARDS_STARTING_PLAYER_FILE;
|
||||
|
||||
SaveLoadKeys(String numberOfFreeMulligans, String mulliganType, String planechase) {
|
||||
SaveLoadKeys(
|
||||
String numberOfFreeMulligans,
|
||||
String mulliganType,
|
||||
String planechase,
|
||||
String emblemCardsEnabled,
|
||||
String emblemCardsPerPlayerFile,
|
||||
String emblemCardsStartingPlayerFile
|
||||
) {
|
||||
NUMBER_OF_FREE_MULLIGANS = numberOfFreeMulligans;
|
||||
MULLIGAN_TYPE = mulliganType;
|
||||
PLANECHASE = planechase;
|
||||
EMBLEM_CARDS_ENABLED = emblemCardsEnabled;
|
||||
EMBLEM_CARDS_PER_PLAYER_FILE = emblemCardsPerPlayerFile;
|
||||
EMBLEM_CARDS_STARTING_PLAYER_FILE = emblemCardsStartingPlayerFile;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CustomOptionsDialog.class);
|
||||
private final SaveLoadKeys saveLoadKeys;
|
||||
private final JButton openButton;
|
||||
private final JFileChooser fcSelectEmblemCardsPerPlayer;
|
||||
private final JFileChooser fcSelectEmblemCardsStartingPlayer;
|
||||
|
||||
/**
|
||||
* Creates new form NewTableDialog
|
||||
|
|
@ -52,6 +82,12 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1));
|
||||
cbMulliganType.setModel(new DefaultComboBoxModel(MulliganType.values()));
|
||||
this.setModal(true);
|
||||
fcSelectEmblemCardsPerPlayer = new JFileChooser();
|
||||
fcSelectEmblemCardsPerPlayer.setAcceptAllFileFilterUsed(false);
|
||||
fcSelectEmblemCardsPerPlayer.addChoosableFileFilter(new DeckFileFilter("dck", "XMage's deck files (*.dck)"));
|
||||
fcSelectEmblemCardsStartingPlayer = new JFileChooser();
|
||||
fcSelectEmblemCardsStartingPlayer.setAcceptAllFileFilterUsed(false);
|
||||
fcSelectEmblemCardsStartingPlayer.addChoosableFileFilter(new DeckFileFilter("dck", "XMage's deck files (*.dck)"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,8 +107,18 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
jSeparator2 = new javax.swing.JSeparator();
|
||||
lblVariantOptions = new javax.swing.JLabel();
|
||||
chkPlaneChase = new javax.swing.JCheckBox();
|
||||
planechaseDescriptionLabel = new javax.swing.JLabel();
|
||||
jSeparator4 = new javax.swing.JSeparator();
|
||||
btnOK = new javax.swing.JButton();
|
||||
jSeparator3 = new javax.swing.JSeparator();
|
||||
chkEmblemCards = new javax.swing.JCheckBox();
|
||||
btnEmblemCardsPerPlayer = new javax.swing.JButton();
|
||||
txtEmblemCardsPerPlayer = new javax.swing.JTextField();
|
||||
lblEmblemCardsPerPlayer = new javax.swing.JLabel();
|
||||
btnEmblemCardsStartingPlayer = new javax.swing.JButton();
|
||||
txtEmblemCardsStartingPlayer = new javax.swing.JTextField();
|
||||
lblEmblemCardsStartingPlayer = new javax.swing.JLabel();
|
||||
emblemCardsDescriptionLabel = new javax.swing.JLabel();
|
||||
|
||||
setTitle("Custom Options");
|
||||
|
||||
|
|
@ -103,7 +149,7 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
lblVariantOptions.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
|
||||
lblVariantOptions.setText("Variant Options");
|
||||
|
||||
chkPlaneChase.setText("PlaneChase");
|
||||
chkPlaneChase.setText("Planechase");
|
||||
chkPlaneChase.setToolTipText("Use the PlaneChase variant for your game.");
|
||||
chkPlaneChase.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
|
@ -111,6 +157,9 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
}
|
||||
});
|
||||
|
||||
planechaseDescriptionLabel.setText("<html>Shared planar deck of all implemented planes.<br>Uses a 9-sided planar die with 2 planeswalk sides and 2 chaos sides.<br>Some ability text may be incorrect.<br>Some rules details (such as who controls plane abilities) may be incorrect.");
|
||||
planechaseDescriptionLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
|
||||
btnOK.setText("OK");
|
||||
btnOK.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
|
@ -118,32 +167,90 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
}
|
||||
});
|
||||
|
||||
chkEmblemCards.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
|
||||
chkEmblemCards.setText("Emblem Cards (Experimental)");
|
||||
chkEmblemCards.setToolTipText("If enabled, select cards to give players emblem copies of");
|
||||
chkEmblemCards.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkEmblemCardsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnEmblemCardsPerPlayer.setText("...");
|
||||
btnEmblemCardsPerPlayer.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnEmblemCardsPerPlayerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
txtEmblemCardsPerPlayer.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtEmblemCardsPerPlayerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblEmblemCardsPerPlayer.setText("Per-Player File");
|
||||
lblEmblemCardsPerPlayer.setToolTipText("An emblem of each card in this file is given to each player");
|
||||
|
||||
btnEmblemCardsStartingPlayer.setText("...");
|
||||
btnEmblemCardsStartingPlayer.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnEmblemCardsStartingPlayerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
txtEmblemCardsStartingPlayer.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtEmblemCardsStartingPlayerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblEmblemCardsStartingPlayer.setText("Starting Player File");
|
||||
lblEmblemCardsStartingPlayer.setToolTipText("An emblem of every card in this file is given to the starting player (useful for symmetric effects)");
|
||||
|
||||
emblemCardsDescriptionLabel.setText("<html>Give players emblems with the abilities of cards.<br>Note that some abilities may not function correctly from the command zone.<br>If anything breaks, please report it on GitHub.");
|
||||
emblemCardsDescriptionLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(jSeparator2)
|
||||
.addComponent(jSeparator4)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSeparator4, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(btnOK))
|
||||
.addComponent(jSeparator3)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(txtEmblemCardsPerPlayer)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnEmblemCardsPerPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(txtEmblemCardsStartingPlayer)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnEmblemCardsStartingPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblMulliganType)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cbMulliganType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblFreeMulligans)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnFreeMulligans, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(chkPlaneChase)
|
||||
.addComponent(lblGeneralOptions)
|
||||
.addComponent(lblVariantOptions))
|
||||
.addGap(0, 125, Short.MAX_VALUE))
|
||||
.addComponent(spnFreeMulligans))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(btnOK)))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblVariantOptions)
|
||||
.addComponent(chkPlaneChase)
|
||||
.addComponent(chkEmblemCards)
|
||||
.addComponent(lblEmblemCardsPerPlayer)
|
||||
.addComponent(lblEmblemCardsStartingPlayer)
|
||||
.addComponent(lblGeneralOptions))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(planechaseDescriptionLabel)
|
||||
.addComponent(emblemCardsDescriptionLabel))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
|
|
@ -166,6 +273,26 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(chkPlaneChase)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(planechaseDescriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(chkEmblemCards)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(emblemCardsDescriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblEmblemCardsPerPlayer)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtEmblemCardsPerPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(btnEmblemCardsPerPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblEmblemCardsStartingPlayer)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtEmblemCardsStartingPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(btnEmblemCardsStartingPlayer, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(btnOK, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
|
|
@ -182,6 +309,14 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
spnFreeMulligans.getAccessibleContext().setAccessibleDescription("Select the number of free mulligans");
|
||||
spnFreeMulligans.getAccessibleContext().setAccessibleParent(lblFreeMulligans);
|
||||
chkPlaneChase.getAccessibleContext().setAccessibleParent(lblVariantOptions);
|
||||
planechaseDescriptionLabel.getAccessibleContext().setAccessibleName("Planechase Description");
|
||||
planechaseDescriptionLabel.getAccessibleContext().setAccessibleDescription("Shared planar deck of all implemented planes.\nUses a 9-sided planar die with 2 planeswalk sides and 2 chaos sides.\nSome ability text may be incorrect.\nSome rules details (such as who controls plane abilities) may be incorrect.");
|
||||
planechaseDescriptionLabel.getAccessibleContext().setAccessibleParent(chkPlaneChase);
|
||||
lblEmblemCardsPerPlayer.getAccessibleContext().setAccessibleParent(chkEmblemCards);
|
||||
txtEmblemCardsStartingPlayer.getAccessibleContext().setAccessibleDescription("");
|
||||
lblEmblemCardsStartingPlayer.getAccessibleContext().setAccessibleParent(chkEmblemCards);
|
||||
emblemCardsDescriptionLabel.getAccessibleContext().setAccessibleName("Emblem Cards description");
|
||||
emblemCardsDescriptionLabel.getAccessibleContext().setAccessibleDescription("Give players emblems with the abilities of cards.\nNote that some abilities may not function correctly from the command zone.\nIf anything breaks, please report it on GitHub.");
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
|
@ -205,10 +340,50 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
updateActiveCount();
|
||||
}//GEN-LAST:event_chkPlaneChaseActionPerformed
|
||||
|
||||
private void chkEmblemCardsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkEmblemCardsActionPerformed
|
||||
updateActiveCount();
|
||||
}//GEN-LAST:event_chkEmblemCardsActionPerformed
|
||||
|
||||
private void btnEmblemCardsPerPlayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEmblemCardsPerPlayerActionPerformed
|
||||
loadEmblemCardFile(false);
|
||||
}//GEN-LAST:event_btnEmblemCardsPerPlayerActionPerformed
|
||||
|
||||
private void txtEmblemCardsPerPlayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtEmblemCardsPerPlayerActionPerformed
|
||||
|
||||
}//GEN-LAST:event_txtEmblemCardsPerPlayerActionPerformed
|
||||
|
||||
private void btnEmblemCardsStartingPlayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEmblemCardsStartingPlayerActionPerformed
|
||||
loadEmblemCardFile(true);
|
||||
}//GEN-LAST:event_btnEmblemCardsStartingPlayerActionPerformed
|
||||
|
||||
private void txtEmblemCardsStartingPlayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtEmblemCardsStartingPlayerActionPerformed
|
||||
|
||||
}//GEN-LAST:event_txtEmblemCardsStartingPlayerActionPerformed
|
||||
|
||||
public void showDialog() {
|
||||
this.setLocation(150, 100);
|
||||
this.setVisible(true);
|
||||
}
|
||||
private void loadEmblemCardFile(boolean isStartingPlayer) {
|
||||
JFileChooser fileChooser = isStartingPlayer ? fcSelectEmblemCardsStartingPlayer : fcSelectEmblemCardsPerPlayer;
|
||||
JTextField textField = isStartingPlayer ? txtEmblemCardsStartingPlayer : txtEmblemCardsPerPlayer;
|
||||
String prefKey = isStartingPlayer ? "lastStartingPlayerEmblemCardsFolder" : "lastPerPlayerEmblemCardsFolder";
|
||||
|
||||
String lastFolder = MageFrame.getPreferences().get(prefKey, "");
|
||||
if (!lastFolder.isEmpty()) {
|
||||
fileChooser.setCurrentDirectory(new File(lastFolder));
|
||||
}
|
||||
int ret = fileChooser.showDialog(this, "Select Emblem Cards");
|
||||
if (ret == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fileChooser.getSelectedFile();
|
||||
textField.setText(file.getPath());
|
||||
try {
|
||||
MageFrame.getPreferences().put(prefKey, file.getCanonicalPath());
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
fileChooser.setSelectedFile(null);
|
||||
}
|
||||
|
||||
public void onLoadSettings(int version) {
|
||||
|
||||
|
|
@ -231,6 +406,9 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
this.chkPlaneChase.setSelected(PreferencesDialog.getCachedValue(saveLoadKeys.PLANECHASE + versionStr, "No").equals("Yes"));
|
||||
this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(saveLoadKeys.NUMBER_OF_FREE_MULLIGANS + versionStr, "0")));
|
||||
this.cbMulliganType.setSelectedItem(MulliganType.valueByName(PreferencesDialog.getCachedValue(saveLoadKeys.MULLIGAN_TYPE + versionStr, MulliganType.GAME_DEFAULT.toString())));
|
||||
this.chkEmblemCards.setSelected(PreferencesDialog.getCachedValue(saveLoadKeys.EMBLEM_CARDS_ENABLED + versionStr, "No").equals("Yes"));
|
||||
this.txtEmblemCardsPerPlayer.setText(PreferencesDialog.getCachedValue(saveLoadKeys.EMBLEM_CARDS_PER_PLAYER_FILE, ""));
|
||||
this.txtEmblemCardsStartingPlayer.setText(PreferencesDialog.getCachedValue(saveLoadKeys.EMBLEM_CARDS_STARTING_PLAYER_FILE, ""));
|
||||
updateActiveCount();
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +428,10 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
PreferencesDialog.saveValue(saveLoadKeys.NUMBER_OF_FREE_MULLIGANS + versionStr, Integer.toString(options.getFreeMulligans()));
|
||||
PreferencesDialog.saveValue(saveLoadKeys.MULLIGAN_TYPE + versionStr, options.getMulliganType().toString());
|
||||
PreferencesDialog.saveValue(saveLoadKeys.PLANECHASE + versionStr, options.isPlaneChase() ? "Yes" : "No");
|
||||
PreferencesDialog.saveValue(saveLoadKeys.EMBLEM_CARDS_ENABLED + versionStr,
|
||||
!(options.getGlobalEmblemCards().isEmpty() && options.getPerPlayerEmblemCards().isEmpty()) ? "Yes" : "No");
|
||||
PreferencesDialog.saveValue(saveLoadKeys.EMBLEM_CARDS_PER_PLAYER_FILE + versionStr, txtEmblemCardsPerPlayer.getText());
|
||||
PreferencesDialog.saveValue(saveLoadKeys.EMBLEM_CARDS_STARTING_PLAYER_FILE + versionStr, txtEmblemCardsStartingPlayer.getText());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -259,6 +441,42 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
options.setFreeMulligans((Integer) spnFreeMulligans.getValue());
|
||||
options.setMullgianType((MulliganType) cbMulliganType.getSelectedItem());
|
||||
options.setPlaneChase(chkPlaneChase.isSelected());
|
||||
if (chkEmblemCards.isSelected()) {
|
||||
if (!txtEmblemCardsPerPlayer.getText().isEmpty()) {
|
||||
Deck perPlayerEmblemDeck = null;
|
||||
try {
|
||||
perPlayerEmblemDeck = Deck.load(DeckImporter.importDeckFromFile(txtEmblemCardsPerPlayer.getText(), true), true, true);
|
||||
} catch (GameException e1) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
if (perPlayerEmblemDeck != null) {
|
||||
perPlayerEmblemDeck.clearLayouts();
|
||||
options.setPerPlayerEmblemCards(perPlayerEmblemDeck.getDeckCardLists().getCards());
|
||||
}
|
||||
else {
|
||||
options.setPerPlayerEmblemCards(Collections.emptySet());
|
||||
}
|
||||
}
|
||||
if (!txtEmblemCardsStartingPlayer.getText().isEmpty()) {
|
||||
Deck startingPlayerEmblemDeck = null;
|
||||
try {
|
||||
startingPlayerEmblemDeck = Deck.load(DeckImporter.importDeckFromFile(txtEmblemCardsStartingPlayer.getText(), true), true, true);
|
||||
} catch (GameException e1) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
if (startingPlayerEmblemDeck != null) {
|
||||
startingPlayerEmblemDeck.clearLayouts();
|
||||
options.setGlobalEmblemCards(startingPlayerEmblemDeck.getDeckCardLists().getCards());
|
||||
}
|
||||
else {
|
||||
options.setGlobalEmblemCards(Collections.emptySet());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
options.setPerPlayerEmblemCards(Collections.emptySet());
|
||||
options.setGlobalEmblemCards(Collections.emptySet());
|
||||
}
|
||||
}
|
||||
|
||||
public void updateActiveCount() {
|
||||
|
|
@ -266,6 +484,7 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
if ((Integer)spnFreeMulligans.getValue() > 0) activeCount++;
|
||||
if (!cbMulliganType.getSelectedItem().toString().equals(MulliganType.GAME_DEFAULT.toString())) activeCount++;
|
||||
if (chkPlaneChase.isSelected()) activeCount++;
|
||||
if (chkEmblemCards.isSelected()) activeCount++;
|
||||
if (activeCount == 0) {
|
||||
openButton.setText("Custom Options...");
|
||||
}
|
||||
|
|
@ -275,15 +494,25 @@ public class CustomOptionsDialog extends MageDialog {
|
|||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton btnEmblemCardsPerPlayer;
|
||||
private javax.swing.JButton btnEmblemCardsStartingPlayer;
|
||||
private javax.swing.JButton btnOK;
|
||||
private javax.swing.JComboBox<String> cbMulliganType;
|
||||
private javax.swing.JCheckBox chkEmblemCards;
|
||||
private javax.swing.JCheckBox chkPlaneChase;
|
||||
private javax.swing.JLabel emblemCardsDescriptionLabel;
|
||||
private javax.swing.JSeparator jSeparator2;
|
||||
private javax.swing.JSeparator jSeparator3;
|
||||
private javax.swing.JSeparator jSeparator4;
|
||||
private javax.swing.JLabel lblEmblemCardsPerPlayer;
|
||||
private javax.swing.JLabel lblEmblemCardsStartingPlayer;
|
||||
private javax.swing.JLabel lblFreeMulligans;
|
||||
private javax.swing.JLabel lblGeneralOptions;
|
||||
private javax.swing.JLabel lblMulliganType;
|
||||
private javax.swing.JLabel lblVariantOptions;
|
||||
private javax.swing.JLabel planechaseDescriptionLabel;
|
||||
private javax.swing.JSpinner spnFreeMulligans;
|
||||
private javax.swing.JTextField txtEmblemCardsPerPlayer;
|
||||
private javax.swing.JTextField txtEmblemCardsStartingPlayer;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,6 +213,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_NEW_TABLE_MINIMUM_RATING = "newTableMinimumRating";
|
||||
public static final String KEY_NEW_TABLE_RATED = "newTableRated";
|
||||
public static final String KEY_NEW_TABLE_EDH_POWER_LEVEL = "newTableEdhPowerLevel";
|
||||
public static final String KEY_NEW_TABLE_EMBLEM_CARDS_ENABLED = "newTableEmblemCardsEnabled";
|
||||
public static final String KEY_NEW_TABLE_EMBLEM_CARDS_PER_PLAYER_FILE = "newTableEmblemCardsPerPlayerFile";
|
||||
public static final String KEY_NEW_TABLE_EMBLEM_CARDS_STARTING_PLAYER_FILE = "newTableEmblemCardsStartingPlayerFile";
|
||||
|
||||
// pref setting for new tournament dialog
|
||||
public static final String KEY_NEW_TOURNAMENT_NAME = "newTournamentName";
|
||||
|
|
@ -237,6 +240,9 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio";
|
||||
public static final String KEY_NEW_TOURNAMENT_MINIMUM_RATING = "newTournamentMinimumRating";
|
||||
public static final String KEY_NEW_TOURNAMENT_RATED = "newTournamentRated";
|
||||
public static final String KEY_NEW_TOURNAMENT_EMBLEM_CARDS_ENABLED = "newTournamentEmblemCardsEnabled";
|
||||
public static final String KEY_NEW_TOURNAMENT_EMBLEM_CARDS_PER_PLAYER_FILE = "newTournamentEmblemCardsPerPlayerFile";
|
||||
public static final String KEY_NEW_TOURNAMENT_EMBLEM_CARDS_STARTING_PLAYER_FILE = "newTournamentEmblemCardsStartingPlayerFile";
|
||||
|
||||
// Settings for auto-choosing targets
|
||||
public static final String KEY_AUTO_TARGET_LEVEL = "autoTargetLevel";
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
+ "<br>Constr.: = Construction time for limited tournament formats"
|
||||
+ "<br>RB = Rollback allowed"
|
||||
+ "<br>PC = Planechase active"
|
||||
+ "<br>EC = One or more emblem cards in use"
|
||||
+ "<br>SP = Spectators allowed"
|
||||
+ "<br>Rng: Range of visibility for multiplayer matches"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -716,8 +716,9 @@ public class CardView extends SimpleCardView {
|
|||
// emblem images are always with common (black) symbol
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
this.expansionSetCode = emblem.getExpansionSetCode();
|
||||
this.cardNumber = "";
|
||||
this.cardNumber = emblem.getCardNumber();
|
||||
this.imageNumber = emblem.getImageNumber();
|
||||
this.usesVariousArt = emblem.getUsesVariousArt();
|
||||
this.rarity = Rarity.COMMON;
|
||||
|
||||
this.playableStats = emblem.playableStats.copy();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.view;
|
||||
|
||||
import mage.cards.Card;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.command.emblems.EmblemOfCard;
|
||||
import mage.players.PlayableObjectStats;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -15,7 +15,9 @@ public class EmblemView implements CommandObjectView, Serializable {
|
|||
|
||||
protected UUID id;
|
||||
protected String name;
|
||||
protected String cardNumber = "";
|
||||
protected int imageNum;
|
||||
protected boolean usesVariousArt = false;
|
||||
protected String expansionSetCode;
|
||||
protected List<String> rules;
|
||||
protected PlayableObjectStats playableStats = new PlayableObjectStats();
|
||||
|
|
@ -26,6 +28,10 @@ public class EmblemView implements CommandObjectView, Serializable {
|
|||
this.imageNum = emblem.getImageNumber();
|
||||
this.expansionSetCode = emblem.getExpansionSetCode();
|
||||
this.rules = emblem.getAbilities().getRules(emblem.getName());
|
||||
if (emblem instanceof EmblemOfCard) {
|
||||
cardNumber = emblem.getCardNumber();
|
||||
usesVariousArt = ((EmblemOfCard) emblem).getUsesVariousArt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -43,10 +49,17 @@ public class EmblemView implements CommandObjectView, Serializable {
|
|||
return id;
|
||||
}
|
||||
|
||||
public String getCardNumber() {
|
||||
return cardNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageNumber() {
|
||||
return imageNum;
|
||||
}
|
||||
public boolean getUsesVariousArt() {
|
||||
return this.usesVariousArt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
|
|
|
|||
|
|
@ -117,6 +117,10 @@ public class TableView implements Serializable {
|
|||
if (table.getMatch().getOptions().isPlaneChase()) {
|
||||
addInfo.append(" PC");
|
||||
}
|
||||
if (!(table.getMatch().getOptions().getPerPlayerEmblemCards().isEmpty())
|
||||
|| !(table.getMatch().getOptions().getGlobalEmblemCards().isEmpty())) {
|
||||
addInfo.append(" EC");
|
||||
}
|
||||
if (table.getMatch().getOptions().isSpectatorsAllowed()) {
|
||||
addInfo.append(" SP");
|
||||
}
|
||||
|
|
@ -177,6 +181,10 @@ public class TableView implements Serializable {
|
|||
if (tourneyMatchOptions.isPlaneChase()) {
|
||||
infoText.append(" PC");
|
||||
}
|
||||
if (!(table.getTournament().getOptions().getMatchOptions().getPerPlayerEmblemCards().isEmpty())
|
||||
|| !(table.getTournament().getOptions().getMatchOptions().getGlobalEmblemCards().isEmpty())) {
|
||||
infoText.append(" EC");
|
||||
}
|
||||
if (table.getTournament().getOptions().isWatchingAllowed()) {
|
||||
infoText.append(" SP");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -628,6 +628,8 @@ public class TableController {
|
|||
gameOptions.rollbackTurnsAllowed = match.getOptions().isRollbackTurnsAllowed();
|
||||
gameOptions.bannedUsers = match.getOptions().getBannedUsers();
|
||||
gameOptions.planeChase = match.getOptions().isPlaneChase();
|
||||
gameOptions.perPlayerEmblemCards = match.getOptions().getPerPlayerEmblemCards();
|
||||
gameOptions.globalEmblemCards = match.getOptions().getGlobalEmblemCards();
|
||||
match.getGame().setGameOptions(gameOptions);
|
||||
managerFactory.gameManager().createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions);
|
||||
String creator = null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,184 @@
|
|||
package org.mage.test.cards.emblems;
|
||||
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.command.emblems.EmblemOfCard;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author artemiswkearney
|
||||
*/
|
||||
public class EmblemOfCardTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testEmblemOfGriselbrand() {
|
||||
// Flying, lifelink
|
||||
// Pay 7 life: Draw seven cards.
|
||||
addEmblem(playerA, new EmblemOfCard(
|
||||
CardRepository.instance.findCard("Griselbrand", true).getMockCard()
|
||||
));
|
||||
|
||||
setLife(playerA, 20);
|
||||
|
||||
assertHandCount(playerA, 0);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pay 7 life: Draw");
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 7);
|
||||
assertLife(playerA, 13);
|
||||
assertEmblemCount(playerA, 1);
|
||||
}
|
||||
@Test
|
||||
public void testEmblemOfYurlok() {
|
||||
// Vigilance
|
||||
// A player losing unspent mana causes that player to lose that much life.
|
||||
// {1}, {T}: Each player adds {B}{R}{G}.
|
||||
addEmblem(playerA, new EmblemOfCard(
|
||||
CardRepository.instance.findCard("Yurlok of Scorch Thrash", true).getMockCard()
|
||||
));
|
||||
|
||||
setLife(playerA, 20);
|
||||
|
||||
// {T}: Add {R}.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
|
||||
checkManaPool("after tapping Mountain", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 1);
|
||||
checkPlayableAbility("can't tap emblem", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}, {T}:", false);
|
||||
|
||||
// wait for mana burn
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
|
||||
checkLife("takes 1 point of mana burn", 1, PhaseStep.BEGIN_COMBAT, playerA, 19);
|
||||
execute();
|
||||
|
||||
assertEmblemCount(playerA, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmblemOfOmniscience() {
|
||||
// You may cast spells from your hand without paying their mana costs.
|
||||
addEmblem(playerA, new EmblemOfCard(
|
||||
CardRepository.instance.findCard("Omniscience", true).getMockCard()
|
||||
));
|
||||
|
||||
// Colossal Dreadmaw {4}{G}{G}
|
||||
// Creature - Dinosaur 6/6
|
||||
// Trample
|
||||
addCard(Zone.HAND, playerA, "Colossal Dreadmaw");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Colossal Dreadmaw");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertPermanentCount(playerA, "Colossal Dreadmaw", 1);
|
||||
assertEmblemCount(playerA, 1);
|
||||
}
|
||||
@Test
|
||||
public void testEmblemOfParadoxEngine() {
|
||||
// Whenever you cast a spell, untap all nonland permanents you control.
|
||||
addEmblem(playerA, new EmblemOfCard(
|
||||
CardRepository.instance.findCard("Paradox Engine", true).getMockCard()
|
||||
));
|
||||
|
||||
// {T}: Add {G}.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mox Emerald");
|
||||
|
||||
// Sol Ring {1}
|
||||
// Artifact
|
||||
// {T}: Add {C}{C}.
|
||||
addCard(Zone.HAND, playerA, "Sol Ring");
|
||||
|
||||
// Basalt Monolith {3}
|
||||
// Artifact
|
||||
// Basalt Monolith doesn’t untap during your untap step.
|
||||
// {T}: Add {C}{C}{C}.
|
||||
// {3}: Untap Basalt Monolith.
|
||||
addCard(Zone.HAND, playerA, "Basalt Monolith");
|
||||
|
||||
// Book of Rass {6}
|
||||
// Artifact
|
||||
// {2}, Pay 2 life: Draw a card.
|
||||
// (just a dummy artifact to cast and spend the mana with)
|
||||
addCard(Zone.HAND, playerA, "Book of Rass");
|
||||
|
||||
setLife(playerA, 20);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sol Ring");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Basalt Monolith");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Book of Rass");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, Pay");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, Pay");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, Pay");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 14);
|
||||
assertEmblemCount(playerA, 1);
|
||||
}
|
||||
@Test
|
||||
public void testEmblemOfDoublingSeason() {
|
||||
// If an effect would create one or more tokens under your control, it
|
||||
// creates twice that many of those tokens instead.
|
||||
// If an effect would put one or more counters on a permanent you
|
||||
// control, it puts twice that many of those counters on that permanent instead.
|
||||
addEmblem(playerA, new EmblemOfCard(
|
||||
CardRepository.instance.findCard("Doubling Season", true).getMockCard()
|
||||
));
|
||||
|
||||
// {T}: Add {W}.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||
|
||||
// Elspeth, Sun's Champion {4}{W}{W}
|
||||
// Legendary Planeswalker — Elspeth
|
||||
// +1: Create three 1/1 white Soldier creature tokens.
|
||||
// −3: Destroy all creatures with power 4 or greater.
|
||||
// −7: You get an emblem with “Creatures you control get +2/+2 and have flying.”
|
||||
// Loyalty: 4
|
||||
addCard(Zone.HAND, playerA, "Elspeth, Sun's Champion");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Elspeth, Sun's Champion");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCounters(
|
||||
"Elspeth's loyalty is doubled",
|
||||
1,
|
||||
PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA,
|
||||
"Elspeth, Sun's Champion",
|
||||
CounterType.LOYALTY,
|
||||
8
|
||||
);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Create");
|
||||
checkPlayableAbility("can't still activate Griselbrand", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pay 7 life:", false);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCounters(
|
||||
"+1 is not doubled",
|
||||
1,
|
||||
PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA,
|
||||
"Elspeth, Sun's Champion",
|
||||
CounterType.LOYALTY,
|
||||
9
|
||||
);
|
||||
checkPermanentCount(
|
||||
"Soldier tokens doubled",
|
||||
1,
|
||||
PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA,
|
||||
"Soldier Token",
|
||||
6
|
||||
);
|
||||
execute();
|
||||
assertEmblemCount(playerA, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1481,6 +1481,13 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
public AbilityImpl copyWithZone(Zone zone) {
|
||||
if (this instanceof MageSingleton) {
|
||||
// not safe to change zone for singletons
|
||||
// in theory there could be some sort of wrapper to effectively change
|
||||
// the zone here, but currently no use of copyWithZone actually needs
|
||||
// to change the zone of any existing singleton abilities
|
||||
return this;
|
||||
}
|
||||
AbilityImpl copy = ((AbilityImpl)this.copy());
|
||||
copy.zone = zone;
|
||||
copy.newId();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import mage.abilities.mana.TriggeredManaAbility;
|
|||
import mage.actions.impl.MageAction;
|
||||
import mage.cards.*;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
|
|
@ -41,6 +42,7 @@ import mage.game.combat.Combat;
|
|||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.command.*;
|
||||
import mage.game.command.dungeons.UndercityDungeon;
|
||||
import mage.game.command.emblems.EmblemOfCard;
|
||||
import mage.game.command.emblems.TheRingEmblem;
|
||||
import mage.game.events.*;
|
||||
import mage.game.events.TableEvent.EventType;
|
||||
|
|
@ -1317,6 +1319,22 @@ public abstract class GameImpl implements Game {
|
|||
addPlane(plane, startingPlayerId);
|
||||
state.setPlaneChase(this, gameOptions.planeChase);
|
||||
}
|
||||
|
||||
if (!gameOptions.perPlayerEmblemCards.isEmpty()) {
|
||||
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
|
||||
for (DeckCardInfo info : gameOptions.perPlayerEmblemCards) {
|
||||
Card card = EmblemOfCard.cardFromDeckInfo(info);
|
||||
addEmblem(new EmblemOfCard(card), card, playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gameOptions.globalEmblemCards.isEmpty()) {
|
||||
for (DeckCardInfo info : gameOptions.globalEmblemCards) {
|
||||
Card card = EmblemOfCard.cardFromDeckInfo(info);
|
||||
addEmblem(new EmblemOfCard(card), card, startingPlayerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void initGameDefaultWatchers() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package mage.game;
|
||||
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.util.Copyable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
@ -52,6 +55,15 @@ public class GameOptions implements Serializable, Copyable<GameOptions> {
|
|||
*/
|
||||
public Set<String> bannedUsers = Collections.emptySet();
|
||||
|
||||
/**
|
||||
* Cards to be given to each player as emblems
|
||||
*/
|
||||
public Collection<DeckCardInfo> perPlayerEmblemCards = Collections.emptySet();
|
||||
/**
|
||||
* Cards to be given to the starting player as emblems
|
||||
*/
|
||||
public Collection<DeckCardInfo> globalEmblemCards = Collections.emptySet();
|
||||
|
||||
|
||||
// PLANECHASE game mode
|
||||
public boolean planeChase = false;
|
||||
|
|
@ -73,6 +85,8 @@ public class GameOptions implements Serializable, Copyable<GameOptions> {
|
|||
this.rollbackTurnsAllowed = options.rollbackTurnsAllowed;
|
||||
this.bannedUsers.addAll(options.bannedUsers);
|
||||
this.planeChase = options.planeChase;
|
||||
this.perPlayerEmblemCards = new HashSet<>(options.perPlayerEmblemCards);
|
||||
this.globalEmblemCards = new HashSet<>(options.globalEmblemCards);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public abstract class Emblem extends CommandObjectImpl {
|
|||
private static final ManaCosts emptyCost = new ManaCostsImpl<>();
|
||||
|
||||
private UUID controllerId;
|
||||
private MageObject sourceObject;
|
||||
protected MageObject sourceObject;
|
||||
private boolean copy;
|
||||
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
|
||||
private FrameStyle frameStyle;
|
||||
|
|
|
|||
108
Mage/src/main/java/mage/game/command/emblems/EmblemOfCard.java
Normal file
108
Mage/src/main/java/mage/game/command/emblems/EmblemOfCard.java
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package mage.game.command.emblems;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.AbilityImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.mock.MockCard;
|
||||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.util.CardUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author artemiswkearney
|
||||
* Emblem with all the abilities of an existing card.
|
||||
* Can be used for custom gamemodes like Omniscience Draft (as seen on Arena),
|
||||
* mana burn with Yurlok of Scorch Thrash, and anything else players might think of.
|
||||
*/
|
||||
public final class EmblemOfCard extends Emblem {
|
||||
private final boolean usesVariousArt;
|
||||
private static final Logger logger = Logger.getLogger(EmblemOfCard.class);
|
||||
|
||||
public static Card lookupCard(
|
||||
String cardName,
|
||||
String cardNumber,
|
||||
String setCode,
|
||||
String infoTypeForError
|
||||
) {
|
||||
int cardNumberInt = CardUtil.parseCardNumberAsInt(cardNumber);
|
||||
List<CardInfo> found = CardRepository.instance.findCards(new CardCriteria()
|
||||
.name(cardName)
|
||||
.minCardNumber(cardNumberInt)
|
||||
.maxCardNumber(cardNumberInt)
|
||||
.setCodes(setCode));
|
||||
return found.stream()
|
||||
.filter(ci -> ci.getCardNumber().equals(cardNumber))
|
||||
.findFirst()
|
||||
.orElseGet(() -> found.stream()
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("No real card for " + infoTypeForError + " " + cardName)))
|
||||
.getCard();
|
||||
}
|
||||
|
||||
public static Card cardFromDeckInfo(DeckCardInfo info) {
|
||||
return lookupCard(
|
||||
info.getCardName(),
|
||||
info.getCardNum(),
|
||||
info.getSetCode(),
|
||||
"DeckCardInfo"
|
||||
);
|
||||
}
|
||||
|
||||
public EmblemOfCard(Card card, Zone zone) {
|
||||
super(card.getName());
|
||||
if (card instanceof MockCard) {
|
||||
card = lookupCard(
|
||||
card.getName(),
|
||||
card.getCardNumber(),
|
||||
card.getExpansionSetCode(),
|
||||
"MockCard"
|
||||
);
|
||||
}
|
||||
this.getAbilities().addAll(card.getAbilities().stream().filter(
|
||||
ability -> zone.match(ability.getZone())
|
||||
).map(ability -> {
|
||||
if (ability instanceof AbilityImpl && ability.getZone() == zone) {
|
||||
return ((AbilityImpl)ability).copyWithZone(Zone.COMMAND);
|
||||
}
|
||||
return ability;
|
||||
}).collect(Collectors.toList()));
|
||||
this.getAbilities().setSourceId(this.getId());
|
||||
this.setExpansionSetCode(card.getExpansionSetCode());
|
||||
this.setCardNumber(card.getCardNumber());
|
||||
this.setImageNumber(card.getImageNumber());
|
||||
this.usesVariousArt = card.getUsesVariousArt();
|
||||
}
|
||||
|
||||
public EmblemOfCard(Card card) {
|
||||
this(card, Zone.BATTLEFIELD);
|
||||
}
|
||||
|
||||
private EmblemOfCard(EmblemOfCard eoc) {
|
||||
super(eoc);
|
||||
this.usesVariousArt = eoc.usesVariousArt;
|
||||
}
|
||||
@Override
|
||||
public EmblemOfCard copy() {
|
||||
return new EmblemOfCard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceObject(MageObject sourceObject) {
|
||||
this.sourceObject = sourceObject;
|
||||
// super method would try and fail to find the emblem image here
|
||||
// (not sure why that would be setSoureObject's job; we get our image during construction)
|
||||
}
|
||||
|
||||
public boolean getUsesVariousArt() {
|
||||
return usesVariousArt;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
package mage.game.match;
|
||||
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.constants.MatchBufferTime;
|
||||
import mage.constants.MatchTimeLimit;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
|
|
@ -11,10 +12,7 @@ import mage.game.result.ResultProtos;
|
|||
import mage.players.PlayerType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -52,6 +50,9 @@ public class MatchOptions implements Serializable {
|
|||
protected MatchBufferTime matchBufferTime; // Amount of time each player gets before their normal time limit counts down. Refreshes each time the normal timer is invoked.
|
||||
protected MulliganType mulliganType;
|
||||
|
||||
protected Collection<DeckCardInfo> perPlayerEmblemCards;
|
||||
protected Collection<DeckCardInfo> globalEmblemCards;
|
||||
|
||||
/*public MatchOptions(String name, String gameType) {
|
||||
this.name = name;
|
||||
this.gameType = gameType;
|
||||
|
|
@ -65,6 +66,8 @@ public class MatchOptions implements Serializable {
|
|||
this.password = "";
|
||||
this.multiPlayer = multiPlayer;
|
||||
this.numSeats = numSeats;
|
||||
this.perPlayerEmblemCards = Collections.emptySet();
|
||||
this.globalEmblemCards = Collections.emptySet();
|
||||
}
|
||||
|
||||
public void setNumSeats (int numSeats) {
|
||||
|
|
@ -288,4 +291,19 @@ public class MatchOptions implements Serializable {
|
|||
return mulliganType;
|
||||
}
|
||||
|
||||
public Collection<DeckCardInfo> getPerPlayerEmblemCards() {
|
||||
return perPlayerEmblemCards;
|
||||
}
|
||||
|
||||
public void setPerPlayerEmblemCards(Collection<DeckCardInfo> perPlayerEmblemCards) {
|
||||
this.perPlayerEmblemCards = perPlayerEmblemCards;
|
||||
}
|
||||
|
||||
public Collection<DeckCardInfo> getGlobalEmblemCards() {
|
||||
return globalEmblemCards;
|
||||
}
|
||||
|
||||
public void setGlobalEmblemCards(Collection<DeckCardInfo> globalEmblemCards) {
|
||||
this.globalEmblemCards = globalEmblemCards;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue