mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 12:02:01 -08:00
Merge branch 'master' of https://github.com/magefree/mage.git into MorphRework_v2
# Conflicts: # Mage.Sets/src/mage/cards/b/Banefire.java
This commit is contained in:
commit
26af2602e4
484 changed files with 6960 additions and 5629 deletions
|
|
@ -250,6 +250,11 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
LOGGER.fatal(null, ex);
|
||||
}
|
||||
|
||||
// other settings
|
||||
if (ClientCallback.SIMULATE_BAD_CONNECTION) {
|
||||
LOGGER.info("Network: bad connection mode enabled");
|
||||
}
|
||||
|
||||
// DATA PREPARE
|
||||
RepositoryUtil.bootstrapLocalDb();
|
||||
// re-create database on empty (e.g. after new build cleaned db on startup)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
package mage.client.cards;
|
||||
|
||||
import mage.cards.CardDimensions;
|
||||
import mage.abilities.icon.CardIconRenderSettings;
|
||||
import mage.cards.CardDimensions;
|
||||
import mage.cards.MageCard;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.draft.DraftPanel;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.comparators.CardViewRarityComparator;
|
||||
import mage.client.util.ClientEventType;
|
||||
import mage.client.util.Event;
|
||||
import mage.client.util.Listener;
|
||||
import mage.client.util.audio.AudioManager;
|
||||
import mage.client.util.comparators.CardViewRarityComparator;
|
||||
import mage.constants.Constants;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CardsView;
|
||||
|
|
@ -28,6 +29,8 @@ public class DraftGrid extends javax.swing.JPanel implements CardEventProducer {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(DraftGrid.class);
|
||||
|
||||
private final DraftPanel parentPanel;
|
||||
|
||||
protected final CardEventSource cardEventSource = new CardEventSource();
|
||||
protected BigCard bigCard;
|
||||
protected MageCard markedCard;
|
||||
|
|
@ -36,22 +39,28 @@ public class DraftGrid extends javax.swing.JPanel implements CardEventProducer {
|
|||
/**
|
||||
* Creates new form DraftGrid
|
||||
*/
|
||||
public DraftGrid() {
|
||||
public DraftGrid(DraftPanel panel) {
|
||||
initComponents();
|
||||
parentPanel = panel;
|
||||
markedCard = null;
|
||||
emptyGrid = true;
|
||||
|
||||
// ENABLE picks and other actions
|
||||
cardEventSource.addListener(new Listener<Event>() {
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
if (event.getEventType() == ClientEventType.CARD_DOUBLE_CLICK) {
|
||||
cardEventSource.addListener(event -> {
|
||||
if (event.getEventType() == ClientEventType.CARD_DOUBLE_CLICK
|
||||
|| event.getEventType() == ClientEventType.CARD_CLICK) {
|
||||
// There is a protection against picking too early in DraftPanel logic.
|
||||
// So, when double clicking early, we do mark the card as selected like
|
||||
// a single click would.
|
||||
|
||||
CardView card = (CardView) event.getSource();
|
||||
if(event.getEventType() == ClientEventType.CARD_DOUBLE_CLICK
|
||||
&& parentPanel.isAllowedToPick()
|
||||
) {
|
||||
cardEventSource.fireEvent(card, ClientEventType.DRAFT_PICK_CARD);
|
||||
hidePopup();
|
||||
AudioManager.playOnDraftSelect();
|
||||
} else if (event.getEventType() == ClientEventType.CARD_CLICK) {
|
||||
CardView card = (CardView) event.getSource();
|
||||
} else {
|
||||
MageCard cardPanel = (MageCard) event.getComponent();
|
||||
if (markedCard != null) {
|
||||
markedCard.setSelected(false);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="tabsPanel" pref="584" max="32767" attributes="0"/>
|
||||
<Component id="tabsPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="saveButton" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
|
||||
|
|
@ -134,14 +134,14 @@
|
|||
<Component class="javax.swing.JCheckBox" name="cbGameLogAutoSave">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" value="Save game logs (to "../Mage.Client/gamelogs/" directory)"/>
|
||||
<Property name="text" type="java.lang.String" value="Save game logs (dest folder: "..\u005cxmage\u005cmage-client\u005cgamelogs")" containsInvalidXMLChars="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The logs of all your games will be saved to the mentioned folder if this option is switched on."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbDraftLogAutoSave">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" value="Save draft logs (to "../Mage.Client/gamelogs/" directory)"/>
|
||||
<Property name="text" type="java.lang.String" value="Save draft logs (dest folder: "..\u005cxmage\u005cmage-client\u005cgamelogs")" containsInvalidXMLChars="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The logs of all your games will be saved to the mentioned folder if this option is switched on."/>
|
||||
<Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
|
||||
<Color id="Default Cursor"/>
|
||||
|
|
@ -151,13 +151,13 @@
|
|||
<Component class="javax.swing.JCheckBox" name="cbLimitedDeckAutoSave">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" value="Save limited decks on submit (to "../Mage.Client/gamelogs/" directory)"/>
|
||||
<Property name="text" type="java.lang.String" value="Save limited decks on submit (dest folder: "..\u005cxmage\u005cmage-client\u005cgamelogs")" containsInvalidXMLChars="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="A .dck file for each limited tournament will be saved to the mentioned folder if this option is switched on."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbGameJsonLogAutoSave">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Save JSON game logs (to "../Mage.Client/gamelogsJson/" directory)"/>
|
||||
<Property name="text" type="java.lang.String" value="Save JSON game logs (dest folder: "..\u005cxmage\u005cmage-client\u005cgamelogs")" containsInvalidXMLChars="true"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="The JSON logs of all your games will be saved to the mentioned folder if this option is switched on."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
|
|
@ -279,28 +279,26 @@
|
|||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="displayLifeOnAvatar" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblTargetAutoChoose" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbTargetAutoChooseLevel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="displayLifeOnAvatar" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="cbAskMoveToGraveOrder" alignment="0" min="-2" pref="596" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="showPlayerNamesPermanently" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="nonLandPermanentsInOnePile" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="cbConfirmEmptyManaPool" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="cbAllowRequestToShowHandCards" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="cbShowStormCounter" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="showAbilityPickerForced" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="315" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
|
@ -317,8 +315,6 @@
|
|||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbAllowRequestToShowHandCards" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbShowStormCounter" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbConfirmEmptyManaPool" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cbAskMoveToGraveOrder" min="-2" max="-2" attributes="0"/>
|
||||
|
|
@ -341,9 +337,6 @@
|
|||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value="nonLandPermanentsInOnePile"/>
|
||||
</AccessibilityProperties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="nonLandPermanentsInOnePileActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="showPlayerNamesPermanently">
|
||||
<Properties>
|
||||
|
|
@ -351,9 +344,6 @@
|
|||
<Property name="text" type="java.lang.String" value="Show player names on avatar permanently"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Instead showing the names only if you hover over the avatar with the mouse, the name is shown all the time."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showPlayerNamesPermanentlyActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="displayLifeOnAvatar">
|
||||
<Properties>
|
||||
|
|
@ -361,9 +351,6 @@
|
|||
<Property name="text" type="java.lang.String" value="Display life on avatar image"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Display the player's life over its avatar image."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="displayLifeOnAvatarActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="showAbilityPickerForced">
|
||||
<Properties>
|
||||
|
|
@ -371,9 +358,6 @@
|
|||
<Property name="text" type="java.lang.String" value="Show ability picker for 1 available option (spells without costs, mdf/split side, adventure)"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="This prevents you from accidently activating abilities what you don't want (example: if you haven't mana to cast main side, but clicks on mdf card and play land instead)"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showAbilityPickerForcedActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbAllowRequestToShowHandCards">
|
||||
<Properties>
|
||||
|
|
@ -381,19 +365,6 @@
|
|||
<Property name="text" type="java.lang.String" value="Allow requests from players and spectators to show your hand cards"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>This is the default setting used for your matches. If activated other players or spectators<br>
of your match can send a request so you can allow them to see your hand cards."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbAllowRequestToShowHandCardsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbShowStormCounter">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" value="Show the number of spell casts during the current turn"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>Adds a little box left to the short keys line with the number<br>
of spells already cast during the current turn (storm counter)."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbShowStormCounterActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbConfirmEmptyManaPool">
|
||||
<Properties>
|
||||
|
|
@ -401,9 +372,6 @@
|
|||
<Property name="text" type="java.lang.String" value="Confirm if you want to pass a phase/step but there is still mana in your mana pool"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>If activated you get a confirm message if you pass priority while stack is empty<br>
 and you still have mana in your mana pool."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbConfirmEmptyManaPoolActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbAskMoveToGraveOrder">
|
||||
<Properties>
|
||||
|
|
@ -411,9 +379,6 @@
|
|||
<Property name="text" type="java.lang.String" value="Ask player for setting order cards go to graveyard"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>If activated and multiple cards go to the graveyard at the same time<br>
the player is asked to set the order of the cards."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbAskMoveToGraveOrderActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblTargetAutoChoose">
|
||||
<Properties>
|
||||
|
|
@ -438,9 +403,6 @@
|
|||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value="Auto-choose targets for player combo box"/>
|
||||
</AccessibilityProperties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbTargetAutoChooseLevelActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
|
|
@ -4237,9 +4199,6 @@
|
|||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbStopAttackActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopBlockWithAny">
|
||||
<Properties>
|
||||
|
|
@ -4248,9 +4207,6 @@
|
|||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbStopBlockWithAnyActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopBlockWithZero">
|
||||
<Properties>
|
||||
|
|
@ -4258,9 +4214,6 @@
|
|||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbStopBlockWithZeroActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopOnNewStackObjects">
|
||||
<Properties>
|
||||
|
|
@ -4271,9 +4224,6 @@
|
|||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbStopOnNewStackObjectsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopOnAllMain">
|
||||
<Properties>
|
||||
|
|
@ -4281,9 +4231,6 @@
|
|||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
<Property name="actionCommand" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbStopOnAllMainActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbStopOnAllEnd">
|
||||
<Properties>
|
||||
|
|
@ -4294,9 +4241,6 @@
|
|||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbStopOnAllEndActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbPassPriorityCast">
|
||||
<Properties>
|
||||
|
|
@ -4307,9 +4251,6 @@
|
|||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbPassPriorityCastActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbPassPriorityActivation">
|
||||
<Properties>
|
||||
|
|
@ -4320,9 +4261,6 @@
|
|||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbPassPriorityActivationActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbAutoOrderTrigger">
|
||||
<Properties>
|
||||
|
|
@ -4333,9 +4271,6 @@
|
|||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbAutoOrderTriggerActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbUseSameSettingsForReplacementEffect">
|
||||
<Properties>
|
||||
|
|
@ -4346,9 +4281,6 @@
|
|||
<Dimension value="[300, 25]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseSameSettingsForReplacementEffectActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
|
|
@ -4668,9 +4600,6 @@
|
|||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtBackgroundImagePath">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBackgroundImagePathActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnBrowseBackgroundImage">
|
||||
<Properties>
|
||||
|
|
@ -4681,9 +4610,6 @@
|
|||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtBattlefieldImagePath">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBattlefieldImagePathActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnBrowseBattlefieldImage">
|
||||
<Properties>
|
||||
|
|
@ -4774,36 +4700,24 @@
|
|||
<Property name="text" type="java.lang.String" value="Enable game sounds"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Sounds that will be played for certain actions (e.g. play land, attack, etc.) during the game."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbEnableGameSoundsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbEnableDraftSounds">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Enable draft sounds"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Sounds that will be played during drafting for card picking or warining if time runs out."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbEnableDraftSoundsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbEnableSkipButtonsSounds">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Enable skip button sounds"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Sounds that will be played if a priority skip action (F4/F5/F7/F9) or cancel skip action (F3) is used."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbEnableSkipButtonsSoundsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="cbEnableOtherSounds">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Enable other sounds"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="Sounds that will be played for actions outside of games (e.g. whisper, player joins your game, player submits a deck ...)."/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbEnableOtherSoundsActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
|
|
@ -4869,9 +4783,6 @@
|
|||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtBattlefieldIBGMPath">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBattlefieldIBGMPathActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnBattlefieldBGMBrowse">
|
||||
<Properties>
|
||||
|
|
@ -5993,9 +5904,6 @@
|
|||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtProxyPort">
|
||||
<Events>
|
||||
<EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="txtProxyPortkeyTyped"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblProxyUserName">
|
||||
<Properties>
|
||||
|
|
@ -6010,17 +5918,11 @@
|
|||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="txtPasswordField">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtPasswordFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="rememberPswd">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Remember Password"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rememberPswdActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel11">
|
||||
<Properties>
|
||||
|
|
@ -6330,7 +6232,7 @@
|
|||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="750" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="807" max="32767" attributes="0"/>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
|
@ -6378,7 +6280,7 @@
|
|||
<Component id="lbThemeHint" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbTheme" min="-2" pref="303" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="303" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="360" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
|
@ -6410,9 +6312,6 @@
|
|||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="cbTheme">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbThemeActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ThemeType>"/>
|
||||
</AuxValues>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_DISPLAY_LIVE_ON_AVATAR = "displayLiveOnAvatar";
|
||||
public static final String KEY_SHOW_ABILITY_PICKER_FORCED = "showAbilityPicker";
|
||||
public static final String KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS = "gameAllowRequestShowHandCards";
|
||||
public static final String KEY_GAME_SHOW_STORM_COUNTER = "gameShowStormCounter";
|
||||
public static final String KEY_GAME_CONFIRM_EMPTY_MANA_POOL = "gameConfirmEmptyManaPool";
|
||||
public static final String KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER = "gameAskMoveToGraveORder";
|
||||
public static final String KEY_GAME_USE_PROFANITY_FILTER = "gameUseProfanityFilter";
|
||||
|
|
@ -214,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";
|
||||
|
|
@ -238,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";
|
||||
|
|
@ -439,7 +444,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
displayLifeOnAvatar = new javax.swing.JCheckBox();
|
||||
showAbilityPickerForced = new javax.swing.JCheckBox();
|
||||
cbAllowRequestToShowHandCards = new javax.swing.JCheckBox();
|
||||
cbShowStormCounter = new javax.swing.JCheckBox();
|
||||
cbConfirmEmptyManaPool = new javax.swing.JCheckBox();
|
||||
cbAskMoveToGraveOrder = new javax.swing.JCheckBox();
|
||||
lblTargetAutoChoose = new javax.swing.JLabel();
|
||||
|
|
@ -644,22 +648,22 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
main_gamelog.add(cbGameLogShowTurnInfo);
|
||||
|
||||
cbGameLogAutoSave.setSelected(true);
|
||||
cbGameLogAutoSave.setText("Save game logs (to \"../Mage.Client/gamelogs/\" directory)");
|
||||
cbGameLogAutoSave.setText("Save game logs (dest folder: \"..\\xmage\\mage-client\\gamelogs\")");
|
||||
cbGameLogAutoSave.setToolTipText("The logs of all your games will be saved to the mentioned folder if this option is switched on.");
|
||||
main_gamelog.add(cbGameLogAutoSave);
|
||||
|
||||
cbDraftLogAutoSave.setSelected(true);
|
||||
cbDraftLogAutoSave.setText("Save draft logs (to \"../Mage.Client/gamelogs/\" directory)");
|
||||
cbDraftLogAutoSave.setText("Save draft logs (dest folder: \"..\\xmage\\mage-client\\gamelogs\")");
|
||||
cbDraftLogAutoSave.setToolTipText("The logs of all your games will be saved to the mentioned folder if this option is switched on.");
|
||||
cbDraftLogAutoSave.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
||||
main_gamelog.add(cbDraftLogAutoSave);
|
||||
|
||||
cbLimitedDeckAutoSave.setSelected(true);
|
||||
cbLimitedDeckAutoSave.setText("Save limited decks on submit (to \"../Mage.Client/gamelogs/\" directory)");
|
||||
cbLimitedDeckAutoSave.setText("Save limited decks on submit (dest folder: \"..\\xmage\\mage-client\\gamelogs\")");
|
||||
cbLimitedDeckAutoSave.setToolTipText("A .dck file for each limited tournament will be saved to the mentioned folder if this option is switched on.");
|
||||
main_gamelog.add(cbLimitedDeckAutoSave);
|
||||
|
||||
cbGameJsonLogAutoSave.setText("Save JSON game logs (to \"../Mage.Client/gamelogsJson/\" directory)");
|
||||
cbGameJsonLogAutoSave.setText("Save JSON game logs (dest folder: \"..\\xmage\\mage-client\\gamelogs\")");
|
||||
cbGameJsonLogAutoSave.setToolTipText("The JSON logs of all your games will be saved to the mentioned folder if this option is switched on.");
|
||||
main_gamelog.add(cbGameJsonLogAutoSave);
|
||||
|
||||
|
|
@ -733,74 +737,30 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
nonLandPermanentsInOnePile.setSelected(true);
|
||||
nonLandPermanentsInOnePile.setText("Put non-land permanents in same row as creatures");
|
||||
nonLandPermanentsInOnePile.setToolTipText("<html>If activated, all non land permanents are shown in one row.<br>\nFirst creatures than other permanents. If not activated, creatures are<br>\nshown in a separate row.");
|
||||
nonLandPermanentsInOnePile.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
nonLandPermanentsInOnePileActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
showPlayerNamesPermanently.setSelected(true);
|
||||
showPlayerNamesPermanently.setText("Show player names on avatar permanently");
|
||||
showPlayerNamesPermanently.setToolTipText("Instead showing the names only if you hover over the avatar with the mouse, the name is shown all the time.");
|
||||
showPlayerNamesPermanently.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showPlayerNamesPermanentlyActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
displayLifeOnAvatar.setSelected(true);
|
||||
displayLifeOnAvatar.setText("Display life on avatar image");
|
||||
displayLifeOnAvatar.setToolTipText("Display the player's life over its avatar image.");
|
||||
displayLifeOnAvatar.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
displayLifeOnAvatarActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
showAbilityPickerForced.setSelected(true);
|
||||
showAbilityPickerForced.setText("Show ability picker for 1 available option (spells without costs, mdf/split side, adventure)");
|
||||
showAbilityPickerForced.setToolTipText("This prevents you from accidently activating abilities what you don't want (example: if you haven't mana to cast main side, but clicks on mdf card and play land instead)");
|
||||
showAbilityPickerForced.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showAbilityPickerForcedActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cbAllowRequestToShowHandCards.setSelected(true);
|
||||
cbAllowRequestToShowHandCards.setText("Allow requests from players and spectators to show your hand cards");
|
||||
cbAllowRequestToShowHandCards.setToolTipText("<html>This is the default setting used for your matches. If activated other players or spectators<br>\nof your match can send a request so you can allow them to see your hand cards.");
|
||||
cbAllowRequestToShowHandCards.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbAllowRequestToShowHandCardsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cbShowStormCounter.setSelected(true);
|
||||
cbShowStormCounter.setText("Show the number of spell casts during the current turn");
|
||||
cbShowStormCounter.setToolTipText("<html>Adds a little box left to the short keys line with the number<br>\nof spells already cast during the current turn (storm counter).");
|
||||
cbShowStormCounter.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbShowStormCounterActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cbConfirmEmptyManaPool.setSelected(true);
|
||||
cbConfirmEmptyManaPool.setText("Confirm if you want to pass a phase/step but there is still mana in your mana pool");
|
||||
cbConfirmEmptyManaPool.setToolTipText("<html>If activated you get a confirm message if you pass priority while stack is empty<br>\n and you still have mana in your mana pool.");
|
||||
cbConfirmEmptyManaPool.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbConfirmEmptyManaPoolActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cbAskMoveToGraveOrder.setSelected(true);
|
||||
cbAskMoveToGraveOrder.setText("Ask player for setting order cards go to graveyard");
|
||||
cbAskMoveToGraveOrder.setToolTipText("<html>If activated and multiple cards go to the graveyard at the same time<br>\nthe player is asked to set the order of the cards.");
|
||||
cbAskMoveToGraveOrder.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbAskMoveToGraveOrderActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblTargetAutoChoose.setText("Auto-choose targets for player:");
|
||||
lblTargetAutoChoose.setToolTipText("<html>\nWhen there is only one possible outcome for targeting, the targets can be chosen for you.\n<br>\n<b>None:</b> All targeting must be done by the player.\n<br>\n<b>Most:</b> All targeting other than feel-bad effects (discarding, destroy, sacrifice, exile) that target you, a card you own, or a permanent/spell you control.\n<br>\n<b>All:</b> All targeting that can be automated will be.");
|
||||
|
|
@ -808,34 +768,27 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
cbTargetAutoChooseLevel.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Off", "Most", "All" }));
|
||||
cbTargetAutoChooseLevel.setSelectedIndex(1);
|
||||
cbTargetAutoChooseLevel.setToolTipText(lblTargetAutoChoose.getToolTipText());
|
||||
cbTargetAutoChooseLevel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbTargetAutoChooseLevelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.jdesktop.layout.GroupLayout main_gameLayout = new org.jdesktop.layout.GroupLayout(main_game);
|
||||
main_game.setLayout(main_gameLayout);
|
||||
main_gameLayout.setHorizontalGroup(
|
||||
main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(displayLifeOnAvatar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(main_gameLayout.createSequentialGroup()
|
||||
.add(main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(main_gameLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.add(lblTargetAutoChoose)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbTargetAutoChooseLevel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.add(displayLifeOnAvatar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(main_gameLayout.createSequentialGroup()
|
||||
.add(main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(cbTargetAutoChooseLevel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.add(cbAskMoveToGraveOrder, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 596, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
.add(main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
|
||||
.add(showPlayerNamesPermanently, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(nonLandPermanentsInOnePile, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(cbConfirmEmptyManaPool, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(cbAllowRequestToShowHandCards, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(cbShowStormCounter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.add(showAbilityPickerForced)))
|
||||
.add(0, 315, Short.MAX_VALUE))
|
||||
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
main_gameLayout.setVerticalGroup(
|
||||
main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
|
|
@ -850,8 +803,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbAllowRequestToShowHandCards)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbShowStormCounter)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbConfirmEmptyManaPool)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(cbAskMoveToGraveOrder)
|
||||
|
|
@ -1443,108 +1394,58 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
cbStopAttack.setText("STOP skips on declare attackers if attackers are available");
|
||||
cbStopAttack.setToolTipText("");
|
||||
cbStopAttack.setActionCommand("");
|
||||
cbStopAttack.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbStopAttackActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbStopAttack);
|
||||
|
||||
cbStopBlockWithAny.setSelected(true);
|
||||
cbStopBlockWithAny.setText("STOP skips on declare blockers if ANY blockers are available");
|
||||
cbStopBlockWithAny.setToolTipText("");
|
||||
cbStopBlockWithAny.setActionCommand("");
|
||||
cbStopBlockWithAny.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbStopBlockWithAnyActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbStopBlockWithAny);
|
||||
|
||||
cbStopBlockWithZero.setText("STOP skips on declare blockers if ZERO blockers are available");
|
||||
cbStopBlockWithZero.setToolTipText("");
|
||||
cbStopBlockWithZero.setActionCommand("");
|
||||
cbStopBlockWithZero.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbStopBlockWithZeroActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbStopBlockWithZero);
|
||||
|
||||
cbStopOnNewStackObjects.setText("Skip to STACK resolved (F10): stop on new objects added (on) or stop until empty (off)");
|
||||
cbStopOnNewStackObjects.setToolTipText("");
|
||||
cbStopOnNewStackObjects.setActionCommand("");
|
||||
cbStopOnNewStackObjects.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbStopOnNewStackObjects.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbStopOnNewStackObjectsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbStopOnNewStackObjects);
|
||||
|
||||
cbStopOnAllMain.setText("Skip to MAIN step (F7): stop on any main steps (on) or stop on your main step (off)");
|
||||
cbStopOnAllMain.setToolTipText("");
|
||||
cbStopOnAllMain.setActionCommand("");
|
||||
cbStopOnAllMain.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbStopOnAllMainActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbStopOnAllMain);
|
||||
|
||||
cbStopOnAllEnd.setText("Skip to END step (F5): stop on any end steps (on) or stop on opponents end step (off)");
|
||||
cbStopOnAllEnd.setToolTipText("");
|
||||
cbStopOnAllEnd.setActionCommand("");
|
||||
cbStopOnAllEnd.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbStopOnAllEnd.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbStopOnAllEndActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbStopOnAllEnd);
|
||||
|
||||
cbPassPriorityCast.setText("Pass priority automatically after you have put a spell on the stack");
|
||||
cbPassPriorityCast.setToolTipText("If activated the system passes priority automatically for you if you have put a spell on the stack.");
|
||||
cbPassPriorityCast.setActionCommand("");
|
||||
cbPassPriorityCast.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbPassPriorityCast.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbPassPriorityCastActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbPassPriorityCast);
|
||||
|
||||
cbPassPriorityActivation.setText("Pass priority automatically after you have put an activated ability on the stack");
|
||||
cbPassPriorityActivation.setToolTipText("If activated the system passes priority for you automatically after you have put an activated ability on the stack.");
|
||||
cbPassPriorityActivation.setActionCommand("");
|
||||
cbPassPriorityActivation.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbPassPriorityActivation.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbPassPriorityActivationActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbPassPriorityActivation);
|
||||
|
||||
cbAutoOrderTrigger.setText("TRIGGERS: auto-choose triggers order for same rule texts (put same triggers to the stack at default order)");
|
||||
cbAutoOrderTrigger.setToolTipText("<HTML>If you put same triggers with same texts on the stack then auto-choose their order.<br/>\nYou can change that settings anytime at the game.");
|
||||
cbAutoOrderTrigger.setActionCommand("");
|
||||
cbAutoOrderTrigger.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbAutoOrderTrigger.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbAutoOrderTriggerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbAutoOrderTrigger);
|
||||
|
||||
cbUseSameSettingsForReplacementEffect.setText("REPLACEMENT EFFECTS: use same auto-choose settings for same cards (choose replacement effects order dialog)");
|
||||
cbUseSameSettingsForReplacementEffect.setToolTipText("<HTML>If you setup auto-choose for one object/card then it will be applied for all other objects with same name.<br/>\nYou can change that settings anytime at the game.");
|
||||
cbUseSameSettingsForReplacementEffect.setActionCommand("");
|
||||
cbUseSameSettingsForReplacementEffect.setPreferredSize(new java.awt.Dimension(300, 25));
|
||||
cbUseSameSettingsForReplacementEffect.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbUseSameSettingsForReplacementEffectActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
phases_stopSettings.add(cbUseSameSettingsForReplacementEffect);
|
||||
|
||||
org.jdesktop.layout.GroupLayout tabPhasesLayout = new org.jdesktop.layout.GroupLayout(tabPhases);
|
||||
|
|
@ -1781,12 +1682,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
});
|
||||
|
||||
txtBackgroundImagePath.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtBackgroundImagePathActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnBrowseBackgroundImage.setText("Browse...");
|
||||
btnBrowseBackgroundImage.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
|
@ -1794,12 +1689,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
});
|
||||
|
||||
txtBattlefieldImagePath.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtBattlefieldImagePathActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnBrowseBattlefieldImage.setText("Browse...");
|
||||
btnBrowseBattlefieldImage.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
|
@ -1892,38 +1781,18 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
|
||||
cbEnableGameSounds.setText("Enable game sounds");
|
||||
cbEnableGameSounds.setToolTipText("Sounds that will be played for certain actions (e.g. play land, attack, etc.) during the game.");
|
||||
cbEnableGameSounds.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbEnableGameSoundsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
sounds_clips.add(cbEnableGameSounds);
|
||||
|
||||
cbEnableDraftSounds.setText("Enable draft sounds");
|
||||
cbEnableDraftSounds.setToolTipText("Sounds that will be played during drafting for card picking or warining if time runs out.");
|
||||
cbEnableDraftSounds.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbEnableDraftSoundsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
sounds_clips.add(cbEnableDraftSounds);
|
||||
|
||||
cbEnableSkipButtonsSounds.setText("Enable skip button sounds");
|
||||
cbEnableSkipButtonsSounds.setToolTipText("Sounds that will be played if a priority skip action (F4/F5/F7/F9) or cancel skip action (F3) is used.");
|
||||
cbEnableSkipButtonsSounds.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbEnableSkipButtonsSoundsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
sounds_clips.add(cbEnableSkipButtonsSounds);
|
||||
|
||||
cbEnableOtherSounds.setText("Enable other sounds");
|
||||
cbEnableOtherSounds.setToolTipText("Sounds that will be played for actions outside of games (e.g. whisper, player joins your game, player submits a deck ...).");
|
||||
cbEnableOtherSounds.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbEnableOtherSoundsActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
sounds_clips.add(cbEnableOtherSounds);
|
||||
|
||||
sounds_backgroundMusic.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Music"));
|
||||
|
|
@ -1940,12 +1809,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
jLabel16.setText("Playing from folder:");
|
||||
jLabel16.setToolTipText("");
|
||||
|
||||
txtBattlefieldIBGMPath.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtBattlefieldIBGMPathActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnBattlefieldBGMBrowse.setText("Browse...");
|
||||
btnBattlefieldBGMBrowse.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
|
|
@ -2518,28 +2381,11 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
|
||||
lblProxyPort.setText("Port:");
|
||||
|
||||
txtProxyPort.addKeyListener(new java.awt.event.KeyAdapter() {
|
||||
public void keyTyped(java.awt.event.KeyEvent evt) {
|
||||
txtProxyPortkeyTyped(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblProxyUserName.setText("User Name:");
|
||||
|
||||
lblProxyPassword.setText("Password:");
|
||||
|
||||
txtPasswordField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtPasswordFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
rememberPswd.setText("Remember Password");
|
||||
rememberPswd.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
rememberPswdActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel11.setFont(new java.awt.Font("Tahoma", 2, 10)); // NOI18N
|
||||
jLabel11.setText("Note: password won't be encrypted!");
|
||||
|
|
@ -2804,12 +2650,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
lbSelectLabel.setPreferredSize(new java.awt.Dimension(110, 16));
|
||||
lbSelectLabel.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
|
||||
|
||||
cbTheme.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cbThemeActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lbThemeHint.setText("Requires a restart to apply new theme.");
|
||||
|
||||
org.jdesktop.layout.GroupLayout themesCategoryLayout = new org.jdesktop.layout.GroupLayout(themesCategory);
|
||||
|
|
@ -2823,7 +2663,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
.add(themesCategoryLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(lbThemeHint)
|
||||
.add(cbTheme, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 303, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap(303, Short.MAX_VALUE))
|
||||
.addContainerGap(360, Short.MAX_VALUE))
|
||||
);
|
||||
themesCategoryLayout.setVerticalGroup(
|
||||
themesCategoryLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
|
|
@ -2840,7 +2680,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
tabThemes.setLayout(tabThemesLayout);
|
||||
tabThemesLayout.setHorizontalGroup(
|
||||
tabThemesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(0, 750, Short.MAX_VALUE)
|
||||
.add(0, 807, Short.MAX_VALUE)
|
||||
.add(tabThemesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(tabThemesLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
|
|
@ -2897,7 +2737,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
|
||||
.add(layout.createSequentialGroup()
|
||||
.add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 584, Short.MAX_VALUE)
|
||||
.add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
|
||||
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
|
||||
.add(saveButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
|
||||
|
|
@ -2920,7 +2760,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
save(prefs, dialog.displayLifeOnAvatar, KEY_DISPLAY_LIVE_ON_AVATAR, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true", "false", UPDATE_CACHE_POLICY);
|
||||
save(prefs, dialog.cbGameLogShowTurnInfo, KEY_GAME_LOG_SHOW_TURN_INFO, "true", "false", UPDATE_CACHE_POLICY);
|
||||
|
|
@ -3097,19 +2936,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
this.showProxySettings();
|
||||
}//GEN-LAST:event_cbProxyTypeActionPerformed
|
||||
|
||||
private void txtPasswordFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordFieldActionPerformed
|
||||
}//GEN-LAST:event_txtPasswordFieldActionPerformed
|
||||
|
||||
private void txtProxyPortkeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtProxyPortkeyTyped
|
||||
}//GEN-LAST:event_txtProxyPortkeyTyped
|
||||
|
||||
private void rememberPswdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rememberPswdActionPerformed
|
||||
}//GEN-LAST:event_rememberPswdActionPerformed
|
||||
|
||||
private void cbEnableGameSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableGameSoundsActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbEnableGameSoundsActionPerformed
|
||||
|
||||
private void cbEnableBattlefieldBGMActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableBattlefieldBGMActionPerformed
|
||||
if (cbEnableBattlefieldBGM.isSelected()) {
|
||||
txtBattlefieldIBGMPath.setEnabled(true);
|
||||
|
|
@ -3206,20 +3032,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
}
|
||||
|
||||
private void txtBackgroundImagePathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtBackgroundImagePathActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtBackgroundImagePathActionPerformed
|
||||
|
||||
private void txtBattlefieldImagePathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtBattlefieldImagePathActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtBattlefieldImagePathActionPerformed
|
||||
|
||||
private void txtBattlefieldIBGMPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtBattlefieldIBGMPathActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtBattlefieldIBGMPathActionPerformed
|
||||
|
||||
private void btnBattlefieldBGMBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBattlefieldBGMBrowseActionPerformed
|
||||
// TODO add your handling code here:
|
||||
int returnVal = fc.showOpenDialog(PreferencesDialog.this);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fc.getSelectedFile();
|
||||
|
|
@ -3227,78 +3040,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
}//GEN-LAST:event_btnBattlefieldBGMBrowseActionPerformed
|
||||
|
||||
private void nonLandPermanentsInOnePileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nonLandPermanentsInOnePileActionPerformed
|
||||
|
||||
}//GEN-LAST:event_nonLandPermanentsInOnePileActionPerformed
|
||||
|
||||
private void showPlayerNamesPermanentlyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showPlayerNamesPermanentlyActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_showPlayerNamesPermanentlyActionPerformed
|
||||
|
||||
private void showCardNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showCardNameActionPerformed
|
||||
|
||||
}//GEN-LAST:event_showCardNameActionPerformed
|
||||
|
||||
private void showAbilityPickerForcedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAbilityPickerForcedActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_showAbilityPickerForcedActionPerformed
|
||||
|
||||
private void cbEnableOtherSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableOtherSoundsActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbEnableOtherSoundsActionPerformed
|
||||
|
||||
private void cbStopAttackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopAttackActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbStopAttackActionPerformed
|
||||
|
||||
private void cbStopBlockWithAnyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopBlockWithAnyActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbStopBlockWithAnyActionPerformed
|
||||
|
||||
private void cbStopOnAllMainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopOnAllMainActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbStopOnAllMainActionPerformed
|
||||
|
||||
private void cbStopOnAllEndActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopOnAllEndActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbStopOnAllEndActionPerformed
|
||||
|
||||
private void cbEnableDraftSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableDraftSoundsActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbEnableDraftSoundsActionPerformed
|
||||
|
||||
private void cbEnableSkipButtonsSoundsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnableSkipButtonsSoundsActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbEnableSkipButtonsSoundsActionPerformed
|
||||
|
||||
private void cbAllowRequestToShowHandCardsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAllowRequestToShowHandCardsActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbAllowRequestToShowHandCardsActionPerformed
|
||||
|
||||
private void cbShowStormCounterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbShowStormCounterActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbShowStormCounterActionPerformed
|
||||
|
||||
private void cbConfirmEmptyManaPoolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbConfirmEmptyManaPoolActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbConfirmEmptyManaPoolActionPerformed
|
||||
|
||||
private void cbAskMoveToGraveOrderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAskMoveToGraveOrderActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbAskMoveToGraveOrderActionPerformed
|
||||
|
||||
private void cbPassPriorityCastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPassPriorityCastActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbPassPriorityCastActionPerformed
|
||||
|
||||
private void cbPassPriorityActivationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPassPriorityActivationActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbPassPriorityActivationActionPerformed
|
||||
|
||||
private void cbAutoOrderTriggerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAutoOrderTriggerActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbAutoOrderTriggerActionPerformed
|
||||
|
||||
private void bttnResetControlsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bttnResetControlsActionPerformed
|
||||
getKeybindButtons().forEach((bttn) -> {
|
||||
String id = bttn.getKey();
|
||||
|
|
@ -3316,18 +3061,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
|
||||
}//GEN-LAST:event_cbBattlefieldFeedbackColorizingModeActionPerformed
|
||||
|
||||
private void displayLifeOnAvatarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_displayLifeOnAvatarActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_displayLifeOnAvatarActionPerformed
|
||||
|
||||
private void cbStopOnNewStackObjectsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopOnNewStackObjectsActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbStopOnNewStackObjectsActionPerformed
|
||||
|
||||
private void cbStopBlockWithZeroActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbStopBlockWithZeroActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbStopBlockWithZeroActionPerformed
|
||||
|
||||
private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbSaveToZipFilesActionPerformed
|
||||
|
|
@ -3349,10 +3082,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
}//GEN-LAST:event_cbUseDefaultImageFolderActionPerformed
|
||||
|
||||
private void cbThemeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbThemeActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbThemeActionPerformed
|
||||
|
||||
private void sliderGUISizeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sliderGUISizeStateChanged
|
||||
// This prevents this event from firing during the initial
|
||||
// setting of the sliders from pref values
|
||||
|
|
@ -3362,14 +3091,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
}
|
||||
}//GEN-LAST:event_sliderGUISizeStateChanged
|
||||
|
||||
private void cbUseSameSettingsForReplacementEffectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbUseSameSettingsForReplacementEffectActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbUseSameSettingsForReplacementEffectActionPerformed
|
||||
|
||||
private void cbTargetAutoChooseLevelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbTargetAutoChooseLevelActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cbTargetAutoChooseLevelActionPerformed
|
||||
|
||||
private void showProxySettings() {
|
||||
Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem();
|
||||
switch (proxyType) {
|
||||
|
|
@ -3482,7 +3203,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
load(prefs, dialog.displayLifeOnAvatar, KEY_DISPLAY_LIVE_ON_AVATAR, "true");
|
||||
load(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true");
|
||||
load(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true");
|
||||
load(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true");
|
||||
load(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true");
|
||||
load(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true");
|
||||
|
||||
|
|
@ -4133,7 +3853,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
private javax.swing.JComboBox<String> cbPreferredImageLanguage;
|
||||
private javax.swing.JComboBox<ProxyType> cbProxyType;
|
||||
private javax.swing.JCheckBox cbSaveToZipFiles;
|
||||
private javax.swing.JCheckBox cbShowStormCounter;
|
||||
private javax.swing.JCheckBox cbStopAttack;
|
||||
private javax.swing.JCheckBox cbStopBlockWithAny;
|
||||
private javax.swing.JCheckBox cbStopBlockWithZero;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Game GUI: choose target card from the cards list (example: exile and choose card to cast)
|
||||
* Game GUI: choose target card from the cards list (example: exile and choose card to cast, choose triggers order, etc)
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
import javax.swing.Timer;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.dnd.DragSourceEvent;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
|
@ -42,6 +41,20 @@
|
|||
private Timer countdown;
|
||||
private int timeout;
|
||||
|
||||
/**
|
||||
* ms delay between booster showing up and pick being allowed.
|
||||
*/
|
||||
private static final int protectionTime = 1500;
|
||||
/**
|
||||
* Timer starting at booster being displayed, to protect from early pick due to clicking
|
||||
* a little too much on the last pick.
|
||||
*/
|
||||
private Timer protectionTimer;
|
||||
/**
|
||||
* Number of the latest card pick for which the protection timer has been set.
|
||||
*/
|
||||
private int protectionPickNo = 0;
|
||||
|
||||
// popup menu area picked cards
|
||||
private final JPopupMenu popupMenuPickedArea;
|
||||
// popup menu for a card
|
||||
|
|
@ -108,6 +121,8 @@
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
protectionTimer = new Timer(protectionTime, e -> protectionTimer.stop());
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
|
|
@ -120,6 +135,13 @@
|
|||
countdown.removeActionListener(al);
|
||||
}
|
||||
}
|
||||
|
||||
if (protectionTimer != null) {
|
||||
protectionTimer.stop();
|
||||
for (ActionListener al : protectionTimer.getActionListeners()) {
|
||||
protectionTimer.removeActionListener(al);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void changeGUISize() {
|
||||
|
|
@ -312,6 +334,12 @@
|
|||
|
||||
if (!draftBooster.isEmptyGrid()) {
|
||||
SessionHandler.setBoosterLoaded(draftId); // confirm to the server that the booster has been successfully loaded, otherwise the server will re-send the booster
|
||||
|
||||
if (pickNo != protectionPickNo && !protectionTimer.isRunning()) {
|
||||
// Restart the protection timer.
|
||||
protectionPickNo = pickNo;
|
||||
protectionTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,6 +373,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isAllowedToPick() {
|
||||
return !protectionTimer.isRunning();
|
||||
}
|
||||
|
||||
public void hideDraft() {
|
||||
Component c = this.getParent();
|
||||
while (c != null && !(c instanceof DraftPane)) {
|
||||
|
|
@ -417,7 +449,7 @@
|
|||
// that's why instead of proactively logging our pick we instead
|
||||
// log *last* pick from the list of picks.
|
||||
// To make this possible we cache the list of cards from the
|
||||
// previous booster and it's sequence number (pack number / pick number)
|
||||
// previous booster and its sequence number (pack number / pick number)
|
||||
// in fields currentBooster and currentBoosterHeader.
|
||||
private void logLastPick(DraftPickView pickView) {
|
||||
if (!isLogging()) {
|
||||
|
|
@ -438,12 +470,14 @@
|
|||
|
||||
private String getCurrentSetCode() {
|
||||
// TODO: Record set codes for random drafts correctly
|
||||
if (setCodes.size() >= packNo) {
|
||||
return setCodes.get(packNo - 1);
|
||||
} else {
|
||||
return " ";
|
||||
if (setCodes != null && setCodes.size() >= packNo) {
|
||||
String setCode = setCodes.get(packNo - 1);
|
||||
if (setCode != null) { // Not sure how, but got a NPE from this method P1P2 in a ZEN/ZEN/WWK draft
|
||||
return setCode;
|
||||
}
|
||||
}
|
||||
return " ";
|
||||
}
|
||||
|
||||
private static boolean isLogging() {
|
||||
String autoSave = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_DRAFT_LOG_AUTO_SAVE, "true");
|
||||
|
|
@ -525,7 +559,7 @@
|
|||
lblPlayer15 = new javax.swing.JLabel();
|
||||
lblPlayer16 = new javax.swing.JLabel();
|
||||
draftPicks = new mage.client.cards.CardsList();
|
||||
draftBooster = new mage.client.cards.DraftGrid();
|
||||
draftBooster = new mage.client.cards.DraftGrid(this);
|
||||
|
||||
draftLeftPane.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
|
||||
draftLeftPane.setFocusable(false);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
|
|||
private FeedbackMode mode;
|
||||
private MageDialog connectedDialog;
|
||||
private ChatPanelBasic connectedChatPanel;
|
||||
private int lastMessageId;
|
||||
private Map<String, Serializable> lastOptions = new HashMap<>();
|
||||
|
||||
private static final ScheduledExecutorService WORKER = Executors.newSingleThreadScheduledExecutor();
|
||||
|
|
@ -66,14 +65,8 @@ public class FeedbackPanel extends javax.swing.JPanel {
|
|||
}
|
||||
|
||||
public void prepareFeedback(FeedbackMode mode, String message, boolean special, Map<String, Serializable> options,
|
||||
int messageId, boolean gameNeedUserFeedback, TurnPhase gameTurnPhase) {
|
||||
boolean gameNeedUserFeedback, TurnPhase gameTurnPhase) {
|
||||
synchronized (this) {
|
||||
if (messageId < this.lastMessageId) {
|
||||
// if too many warning messages here then look at GAME_REDRAW_GUI event logic
|
||||
LOGGER.warn("catch un-synced message from later source (possible reason: connection or performance problems): " + messageId + ", text=" + message);
|
||||
return;
|
||||
}
|
||||
this.lastMessageId = messageId;
|
||||
this.lastOptions = options;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import mage.client.components.KeyboundButton;
|
|||
import mage.client.components.MageComponents;
|
||||
import mage.client.components.ext.dlg.DialogManager;
|
||||
import mage.client.components.layout.RelativeLayout;
|
||||
import mage.client.components.tray.MageTray;
|
||||
import mage.client.dialog.*;
|
||||
import mage.client.dialog.CardInfoWindowDialog.ShowType;
|
||||
import mage.client.game.FeedbackPanel.FeedbackMode;
|
||||
|
|
@ -122,8 +123,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
private JPopupMenu popupMenuTriggerOrder;
|
||||
|
||||
// keep game data for updates/re-draws
|
||||
// warning, it keeps updates from GAME_UPDATE events only and ignore another events with GameView
|
||||
static class LastGameData {
|
||||
int messageId;
|
||||
GameView game;
|
||||
boolean showPlayable;
|
||||
Map<String, Serializable> options;
|
||||
|
|
@ -366,7 +367,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
jSplitPane1.setDividerSize(GUISizeHelper.dividerBarSize);
|
||||
jSplitPane2.setDividerSize(GUISizeHelper.dividerBarSize);
|
||||
|
||||
txtSpellsCast.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize()));
|
||||
txtHoldPriority.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize()));
|
||||
GUISizeHelper.changePopupMenuFont(popupMenuTriggerOrder);
|
||||
|
||||
|
|
@ -390,6 +390,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
stackObjects.setPreferredSize(newDimension);
|
||||
stackObjects.setMinimumSize(newDimension);
|
||||
stackObjects.setMaximumSize(newDimension);
|
||||
stackObjects.changeGUISize(); // must call to cards fit
|
||||
|
||||
newDimension = new Dimension(newStackWidth, (int) pnlShortCuts.getPreferredSize().getHeight());
|
||||
pnlShortCuts.setPreferredSize(newDimension);
|
||||
|
|
@ -501,6 +502,10 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
} else {
|
||||
// play start sound
|
||||
AudioManager.playYourGameStarted();
|
||||
if (!AppUtil.isAppActive()) {
|
||||
MageTray.instance.displayMessage("Your match has started!");
|
||||
MageTray.instance.blink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -571,7 +576,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void init(GameView game) {
|
||||
public synchronized void init(int messageId, GameView game) {
|
||||
addPlayers(game);
|
||||
// default menu states
|
||||
setMenuStates(
|
||||
|
|
@ -581,7 +586,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
holdingPriority
|
||||
);
|
||||
|
||||
updateGame(game);
|
||||
updateGame(messageId, game);
|
||||
}
|
||||
|
||||
private void addPlayers(GameView game) {
|
||||
|
|
@ -706,12 +711,12 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
*/
|
||||
}
|
||||
|
||||
public synchronized void updateGame(GameView game) {
|
||||
updateGame(game, false, null, null);
|
||||
public synchronized void updateGame(int messageId, GameView game) {
|
||||
updateGame(messageId, game, false, null, null);
|
||||
}
|
||||
|
||||
public synchronized void updateGame(GameView game, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
|
||||
keepLastGameData(game, showPlayable, options, targets);
|
||||
public synchronized void updateGame(int messageId, GameView game, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
|
||||
keepLastGameData(messageId, game, showPlayable, options, targets);
|
||||
prepareSelectableView();
|
||||
updateGame();
|
||||
}
|
||||
|
|
@ -777,12 +782,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
logger.debug("Step is empty");
|
||||
this.txtStep.setText("");
|
||||
}
|
||||
if (lastGameData.game.getSpellsCastCurrentTurn() > 0 && PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_SHOW_STORM_COUNTER, "true").equals("true")) {
|
||||
this.txtSpellsCast.setVisible(true);
|
||||
this.txtSpellsCast.setText(' ' + Integer.toString(lastGameData.game.getSpellsCastCurrentTurn()) + ' ');
|
||||
} else {
|
||||
this.txtSpellsCast.setVisible(false);
|
||||
}
|
||||
|
||||
this.txtActivePlayer.setText(lastGameData.game.getActivePlayerName());
|
||||
this.txtPriority.setText(lastGameData.game.getPriorityPlayerName());
|
||||
|
|
@ -946,6 +945,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
//logger.info("game update, message = " + lastGameData.messageId + ", options = " + lastGameData.options + ", priority = " + lastGameData.game.getPriorityPlayerName());
|
||||
feedbackPanel.disableUndo();
|
||||
feedbackPanel.updateOptions(lastGameData.options);
|
||||
|
||||
|
|
@ -1361,12 +1361,13 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
windowMap.entrySet().removeIf(entry -> entry.getValue().isClosed());
|
||||
}
|
||||
|
||||
public void ask(String question, GameView gameView, int messageId, Map<String, Serializable> options) {
|
||||
updateGame(gameView, false, options, null);
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase());
|
||||
public void ask(int messageId, GameView gameView, String question, Map<String, Serializable> options) {
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.QUESTION, question, false, options, true, gameView.getPhase());
|
||||
}
|
||||
|
||||
private void keepLastGameData(GameView game, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
|
||||
private void keepLastGameData(int messageId, GameView game, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
|
||||
lastGameData.messageId = messageId;
|
||||
lastGameData.game = game;
|
||||
lastGameData.showPlayable = showPlayable;
|
||||
lastGameData.options = options;
|
||||
|
|
@ -1623,8 +1624,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
* @param options
|
||||
* @param messageId
|
||||
*/
|
||||
public void pickTarget(GameView gameView, Map<String, Serializable> options, String message, CardsView cardsView, Set<UUID> targets, boolean required, int messageId) {
|
||||
updateGame(gameView, false, options, targets);
|
||||
public void pickTarget(int messageId, GameView gameView, Map<String, Serializable> options, String message, CardsView cardsView, Set<UUID> targets, boolean required) {
|
||||
updateGame(messageId, gameView, false, options, targets);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
clearPickTargetDialogs();
|
||||
|
|
@ -1652,28 +1653,28 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
dialog = prepareCardsDialog(message, cardsView, required, options0, popupMenuType);
|
||||
options0.put("dialog", dialog);
|
||||
}
|
||||
this.feedbackPanel.prepareFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, messageId, true, gameView.getPhase());
|
||||
this.feedbackPanel.prepareFeedback(required ? FeedbackMode.INFORM : FeedbackMode.CANCEL, message, gameView.getSpecial(), options0, true, gameView.getPhase());
|
||||
if (dialog != null) {
|
||||
this.pickTarget.add(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
public void inform(String information, GameView gameView, int messageId) {
|
||||
updateGame(gameView);
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.INFORM, information, gameView.getSpecial(), null, messageId, false, gameView.getPhase());
|
||||
public void inform(int messageId, GameView gameView, String information) {
|
||||
updateGame(messageId, gameView);
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.INFORM, information, gameView.getSpecial(), null, false, gameView.getPhase());
|
||||
}
|
||||
|
||||
public void endMessage(GameView gameView, Map<String, Serializable> options, String message, int messageId) {
|
||||
updateGame(gameView, false, options, null);
|
||||
public void endMessage(int messageId, GameView gameView, Map<String, Serializable> options, String message) {
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.END, message, false, null, messageId, true, null);
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.END, message, false, null, true, null);
|
||||
ArrowBuilder.getBuilder().removeAllArrows(gameId);
|
||||
}
|
||||
|
||||
public void select(GameView gameView, Map<String, Serializable> options, String message, int messageId) {
|
||||
updateGame(gameView, true, options, null);
|
||||
public void select(int messageId, GameView gameView, Map<String, Serializable> options, String message) {
|
||||
updateGame(messageId, gameView, true, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
|
|
@ -1716,31 +1717,31 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
priorityPlayerText = " / priority " + gameView.getPriorityPlayerName();
|
||||
}
|
||||
String messageToDisplay = message + FeedbackPanel.getSmallText(activePlayerText + " / " + gameView.getStep().toString() + priorityPlayerText);
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.SELECT, messageToDisplay, gameView.getSpecial(), panelOptions, messageId, true, gameView.getPhase());
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.SELECT, messageToDisplay, gameView.getSpecial(), panelOptions, true, gameView.getPhase());
|
||||
}
|
||||
|
||||
public void playMana(GameView gameView, Map<String, Serializable> options, String message, int messageId) {
|
||||
updateGame(gameView, true, options, null);
|
||||
public void playMana(int messageId, GameView gameView, Map<String, Serializable> options, String message) {
|
||||
updateGame(messageId, gameView, true, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase());
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, true, gameView.getPhase());
|
||||
}
|
||||
|
||||
public void playXMana(GameView gameView, Map<String, Serializable> options, String message, int messageId) {
|
||||
updateGame(gameView, true, options, null);
|
||||
public void playXMana(int messageId, GameView gameView, Map<String, Serializable> options, String message) {
|
||||
updateGame(messageId, gameView, true, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase());
|
||||
this.feedbackPanel.prepareFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, true, gameView.getPhase());
|
||||
}
|
||||
|
||||
public void replayMessage(String message) {
|
||||
//TODO: implement this
|
||||
}
|
||||
|
||||
public void pickAbility(GameView gameView, Map<String, Serializable> options, AbilityPickerView choices) {
|
||||
updateGame(gameView, false, options, null);
|
||||
public void pickAbility(int messageId, GameView gameView, Map<String, Serializable> options, AbilityPickerView choices) {
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
|
|
@ -1764,8 +1765,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
return showCards;
|
||||
}
|
||||
|
||||
public void getAmount(GameView gameView, Map<String, Serializable> options, int min, int max, String message) {
|
||||
updateGame(gameView, false, options, null);
|
||||
public void getAmount(int messageId, GameView gameView, Map<String, Serializable> options, int min, int max, String message) {
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
|
|
@ -1777,9 +1778,9 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
public void getMultiAmount(List<MultiAmountMessage> messages, GameView gameView, Map<String, Serializable> options,
|
||||
public void getMultiAmount(int messageId, GameView gameView, List<MultiAmountMessage> messages, Map<String, Serializable> options,
|
||||
int min, int max) {
|
||||
updateGame(gameView, false, options, null);
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
|
|
@ -1787,8 +1788,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
SessionHandler.sendPlayerString(gameId, pickMultiNumber.getMultiAmount());
|
||||
}
|
||||
|
||||
public void getChoice(GameView gameView, Map<String, Serializable> options, Choice choice, UUID objectId) {
|
||||
updateGame(gameView, false, options, null);
|
||||
public void getChoice(int messageId, GameView gameView, Map<String, Serializable> options, Choice choice, UUID objectId) {
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
|
|
@ -1813,8 +1814,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
pickChoice.removeDialog();
|
||||
}
|
||||
|
||||
public void pickPile(GameView gameView, Map<String, Serializable> options, String message, CardsView pile1, CardsView pile2) {
|
||||
updateGame(gameView, false, options, null);
|
||||
public void pickPile(int messageId, GameView gameView, Map<String, Serializable> options, String message, CardsView pile1, CardsView pile2) {
|
||||
updateGame(messageId, gameView, false, options, null);
|
||||
hideAll();
|
||||
DialogManager.getManager(gameId).fadeOut();
|
||||
|
||||
|
|
@ -1856,14 +1857,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
lblPriority = new javax.swing.JLabel();
|
||||
feedbackPanel = new mage.client.game.FeedbackPanel();
|
||||
|
||||
txtSpellsCast = new javax.swing.JLabel();
|
||||
Border paddingBorder = BorderFactory.createEmptyBorder(4, 4, 4, 4);
|
||||
Border border = BorderFactory.createLineBorder(Color.DARK_GRAY, 2);
|
||||
txtSpellsCast.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder));
|
||||
txtSpellsCast.setBackground(Color.LIGHT_GRAY);
|
||||
txtSpellsCast.setOpaque(true);
|
||||
txtSpellsCast.setToolTipText("spells cast during the current turn");
|
||||
|
||||
txtHoldPriority = new javax.swing.JLabel();
|
||||
txtHoldPriority.setText("Hold");
|
||||
txtHoldPriority.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder));
|
||||
|
|
@ -2336,7 +2331,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
)
|
||||
.addGroup(gl_pnlShortCuts.createSequentialGroup()
|
||||
.addComponent(txtHoldPriority)
|
||||
.addComponent(txtSpellsCast)
|
||||
/*.addComponent(btnToggleMacro)*/
|
||||
.addComponent(btnSwitchHands)
|
||||
.addComponent(btnCancelSkip)
|
||||
|
|
@ -2372,7 +2366,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
.addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
/*.addComponent(btnToggleMacro)*/
|
||||
.addComponent(txtHoldPriority)
|
||||
.addComponent(txtSpellsCast)
|
||||
.addComponent(btnSwitchHands)
|
||||
.addComponent(btnCancelSkip)
|
||||
.addComponent(btnConcede)
|
||||
|
|
@ -2808,6 +2801,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
if (!cardViewPopupMenu.getAbility().getRules().isEmpty()
|
||||
&& !cardViewPopupMenu.getAbility().getRules().get(0).isEmpty()) {
|
||||
abilityRuleText = cardViewPopupMenu.getAbility().getRules().get(0);
|
||||
abilityRuleText = abilityRuleText.replace("{this}", cardViewPopupMenu.getName());
|
||||
}
|
||||
}
|
||||
switch (e.getActionCommand()) {
|
||||
|
|
@ -3001,7 +2995,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
private javax.swing.JSplitPane jSplitPane2;
|
||||
private JPanel jPhases;
|
||||
private JPanel phasesContainer;
|
||||
private javax.swing.JLabel txtSpellsCast;
|
||||
private javax.swing.JLabel txtHoldPriority;
|
||||
|
||||
private HoverButton currentStep;
|
||||
|
|
|
|||
|
|
@ -105,12 +105,20 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
timer.setTaskOnTick(() -> {
|
||||
int priorityTimeValue = pt.getCount() + pt.getBufferCount();
|
||||
String text = getPriorityTimeLeftString(priorityTimeValue);
|
||||
|
||||
// Set timer text colors (note, if you change it here, change it in update() as well)
|
||||
Color textColor = null; // use default in HoverButton
|
||||
Color foregroundColor = Color.BLACK;
|
||||
if (pt.getBufferCount() > 0) {
|
||||
textColor = Color.GREEN;
|
||||
foregroundColor = Color.GREEN.darker().darker();
|
||||
} else if (pt.getCount() < 300) { // visual indication for under 5 minutes
|
||||
textColor = Color.RED;
|
||||
foregroundColor = Color.RED.darker().darker();
|
||||
}
|
||||
PlayerPanelExt.this.avatar.setTopText(text);
|
||||
PlayerPanelExt.this.avatar.setTopTextColor(pt.getBufferCount() > 0 ? Color.GREEN : null);
|
||||
PlayerPanelExt.this.avatar.setTopTextColor(textColor);
|
||||
PlayerPanelExt.this.timerLabel.setText(text);
|
||||
PlayerPanelExt.this.timerLabel
|
||||
.setForeground(pt.getBufferCount() > 0 ? Color.GREEN.darker().darker() : Color.BLACK);
|
||||
PlayerPanelExt.this.timerLabel.setForeground(foregroundColor);
|
||||
PlayerPanelExt.this.avatar.repaint();
|
||||
});
|
||||
timer.init(gameId);
|
||||
|
|
@ -195,10 +203,10 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
if (playerLife != pastLife) {
|
||||
if (playerLife > pastLife) {
|
||||
avatar.gainLifeDisplay();
|
||||
} else if (playerLife < pastLife) {
|
||||
} else {
|
||||
avatar.loseLifeDisplay();
|
||||
}
|
||||
} else if (playerLife == pastLife) {
|
||||
} else {
|
||||
avatar.stopLifeDisplay();
|
||||
}
|
||||
}
|
||||
|
|
@ -311,10 +319,18 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
this.timer.setBufferCount(player.getBufferTimeLeft());
|
||||
this.avatar.setTopText(priorityTimeValue);
|
||||
this.timerLabel.setText(priorityTimeValue);
|
||||
|
||||
this.avatar.setTopTextColor(player.getBufferTimeLeft() > 0 ? Color.GREEN : null);
|
||||
this.timerLabel
|
||||
.setForeground(player.getBufferTimeLeft() > 0 ? Color.GREEN.darker().darker() : Color.BLACK);
|
||||
// Set timer text colors (note, if you change it here, change it in init()::timer.setTaskOnTick() as well)
|
||||
Color textColor = null; // use default in HoverButton
|
||||
Color foregroundColor = Color.BLACK;
|
||||
if (player.getBufferTimeLeft() > 0) {
|
||||
textColor = Color.GREEN;
|
||||
foregroundColor = Color.GREEN.darker().darker();
|
||||
} else if (player.getPriorityTimeLeft() < 300) { // visual indication for under 5 minutes
|
||||
textColor = Color.RED;
|
||||
foregroundColor = Color.RED.darker().darker();
|
||||
}
|
||||
this.avatar.setTopTextColor(textColor);
|
||||
this.timerLabel.setForeground(foregroundColor);
|
||||
}
|
||||
if (player.isTimerActive()) {
|
||||
this.timer.resume();
|
||||
|
|
@ -360,25 +376,17 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
private void updateAvatar() {
|
||||
if (flagName == null) { // do only once
|
||||
avatar.setText(this.player.getName());
|
||||
if (!player.getUserData().getFlagName().equals(flagName)) {
|
||||
flagName = player.getUserData().getFlagName();
|
||||
this.avatar.setTopTextImage(CountryUtil.getCountryFlagIconSize(flagName, 11).getImage());
|
||||
}
|
||||
// TODO: Add the wins to the tooltiptext of the avatar
|
||||
String countryname = CountryUtil.getCountryName(flagName);
|
||||
if (countryname == null) {
|
||||
countryname = "Unknown";
|
||||
}
|
||||
String countryName = CountryUtil.getCountryName(flagName);
|
||||
basicTooltipText = "<HTML>Name: " + player.getName()
|
||||
+ "<br/>Flag: " + countryname
|
||||
+ "<br/>Constructed rating: " + player.getUserData().getConstructedRating()
|
||||
+ "<br/>Limited rating: " + player.getUserData().getLimitedRating()
|
||||
+ "<br/>Flag: " + (countryName == null ? "Unknown" : countryName)
|
||||
+ "<br/>Deck hash code: " + player.getDeckHashCode()
|
||||
+ "<br/>This match wins: " + player.getWins() + " of " + player.getWinsNeeded() + " (to win the match)"
|
||||
+ (player.getUserData() == null ? "" : "<br/>History: " + player.getUserData().getHistory());
|
||||
+ "<br/>This match wins: " + player.getWins() + " of " + player.getWinsNeeded() + " (to win the match)";
|
||||
}
|
||||
// Extend tooltip
|
||||
StringBuilder tooltipText = new StringBuilder(basicTooltipText);
|
||||
tooltipText.append("<br/>Match time remaining: ").append(getPriorityTimeLeftString(player));
|
||||
this.avatar.setTopTextImageRight(null);
|
||||
for (String name : player.getDesignationNames()) {
|
||||
tooltipText.append("<br/>").append(name);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import mage.client.util.audio.AudioManager;
|
|||
import mage.client.util.object.SaveObjectUtil;
|
||||
import mage.interfaces.callback.CallbackClient;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
import mage.interfaces.callback.ClientCallbackType;
|
||||
import mage.remote.ActionData;
|
||||
import mage.remote.Session;
|
||||
import mage.view.*;
|
||||
|
|
@ -24,8 +25,7 @@ import org.apache.log4j.Logger;
|
|||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -34,38 +34,76 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(CallbackClientImpl.class);
|
||||
private final MageFrame frame;
|
||||
private int messageId = 0;
|
||||
private int gameInformMessageId = 0;
|
||||
private final Map<ClientCallbackType, Integer> lastMessages;
|
||||
|
||||
public CallbackClientImpl(MageFrame frame) {
|
||||
this.frame = frame;
|
||||
this.lastMessages = new HashMap<>();
|
||||
Arrays.stream(ClientCallbackType.values()).forEach(t -> this.lastMessages.put(t, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void processCallback(final ClientCallback callback) {
|
||||
callback.decompressData();
|
||||
|
||||
// put replay related code here
|
||||
SaveObjectUtil.saveObject(callback.getData(), callback.getMethod().toString());
|
||||
|
||||
// all GUI related code must be executed in swing thread
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
logger.debug(callback.getMessageId() + " -- " + callback.getMethod());
|
||||
logger.debug("message " + callback.getMessageId() + " - " + callback.getMethod().getType() + " - " + callback.getMethod());
|
||||
|
||||
// process bad connection (events can income in wrong order, so outdated data must be ignored)
|
||||
// - table/dialog events like game start, game end, choose dialog - must be processed anyway
|
||||
// - messages events like chat, inform, error - must be processed anyway
|
||||
// - update events like opponent priority - can be ignored
|
||||
if (!callback.getMethod().getType().equals(ClientCallbackType.CLIENT_SIDE_EVENT)) {
|
||||
int lastAnyMessageId = this.lastMessages.values().stream().mapToInt(x -> x).max().orElse(0);
|
||||
if (lastAnyMessageId > callback.getMessageId()) {
|
||||
// un-synced message
|
||||
if (callback.getMethod().getType().mustIgnoreOnOutdated()) {
|
||||
// ignore
|
||||
logger.warn(String.format("ignore un-synced message %d - %s - %s, possible reason: slow connection/performance",
|
||||
callback.getMessageId(),
|
||||
callback.getMethod().getType(),
|
||||
callback.getMethod()
|
||||
));
|
||||
return;
|
||||
} else {
|
||||
// process it anyway
|
||||
logger.debug(String.format("processing un-synced message %d - %s - %s, possible reason: slow connection/performance",
|
||||
callback.getMessageId(),
|
||||
callback.getMethod().getType(),
|
||||
callback.getMethod()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// keep track of synced messages only
|
||||
if (!callback.getMethod().getType().canComeInAnyOrder()) {
|
||||
this.lastMessages.put(callback.getMethod().getType(), callback.getMessageId());
|
||||
}
|
||||
}
|
||||
|
||||
switch (callback.getMethod()) {
|
||||
|
||||
case START_GAME: {
|
||||
TableClientMessage message = (TableClientMessage) callback.getData();
|
||||
GameManager.instance.setCurrentPlayerUUID(message.getPlayerId());
|
||||
gameStarted(message.getGameId(), message.getPlayerId());
|
||||
gameStarted(callback.getMessageId(), message.getGameId(), message.getPlayerId());
|
||||
break;
|
||||
}
|
||||
|
||||
case START_TOURNAMENT: {
|
||||
TableClientMessage message = (TableClientMessage) callback.getData();
|
||||
tournamentStarted(message.getGameId(), message.getPlayerId());
|
||||
tournamentStarted(callback.getMessageId(), message.getGameId(), message.getPlayerId());
|
||||
break;
|
||||
}
|
||||
|
||||
case START_DRAFT: {
|
||||
TableClientMessage message = (TableClientMessage) callback.getData();
|
||||
draftStarted(message.getGameId(), message.getPlayerId());
|
||||
draftStarted(callback.getMessageId(), message.getGameId(), message.getPlayerId());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +187,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case REPLAY_INIT: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
panel.init((GameView) callback.getData());
|
||||
panel.init(callback.getMessageId(), (GameView) callback.getData());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -157,7 +195,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case REPLAY_DONE: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
panel.endMessage(null, null, (String) callback.getData(), callback.getMessageId());
|
||||
panel.endMessage(callback.getMessageId(), null, null, (String) callback.getData());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -165,7 +203,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case REPLAY_UPDATE: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
panel.updateGame((GameView) callback.getData());
|
||||
panel.updateGame(callback.getMessageId(), (GameView) callback.getData());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -174,7 +212,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_INIT", callback.getObjectId(), callback.getData());
|
||||
panel.init((GameView) callback.getData());
|
||||
panel.init(callback.getMessageId(), (GameView) callback.getData());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -190,7 +228,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
String logFileName = "game-" + gameId + ".json";
|
||||
S3Uploader.upload(logFileName, gameId.toString());
|
||||
}
|
||||
panel.endMessage(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId());
|
||||
panel.endMessage(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -205,7 +243,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_ASK", callback.getObjectId(), message);
|
||||
panel.ask(message.getMessage(), message.getGameView(), callback.getMessageId(), message.getOptions());
|
||||
panel.ask(callback.getMessageId(), message.getGameView(), message.getMessage(), message.getOptions());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -216,8 +254,8 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_TARGET", callback.getObjectId(), message);
|
||||
panel.pickTarget(message.getGameView(), message.getOptions(), message.getMessage(),
|
||||
message.getCardsView1(), message.getTargets(), message.isFlag(), callback.getMessageId());
|
||||
panel.pickTarget(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMessage(),
|
||||
message.getCardsView1(), message.getTargets(), message.isFlag());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -227,7 +265,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_SELECT", callback.getObjectId(), message);
|
||||
panel.select(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId());
|
||||
panel.select(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -237,7 +275,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_CHOOSE_ABILITY", callback.getObjectId(), callback.getData());
|
||||
panel.pickAbility(abilityPickerView.getGameView(), null, abilityPickerView);
|
||||
panel.pickAbility(callback.getMessageId(), abilityPickerView.getGameView(), null, abilityPickerView);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -247,7 +285,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_CHOOSE_PILE", callback.getObjectId(), message);
|
||||
panel.pickPile(message.getGameView(), message.getOptions(), message.getMessage(), message.getCardsView1(), message.getCardsView2());
|
||||
panel.pickPile(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMessage(), message.getCardsView1(), message.getCardsView2());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -257,7 +295,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_CHOOSE_CHOICE", callback.getObjectId(), message);
|
||||
panel.getChoice(message.getGameView(), message.getOptions(), message.getChoice(), callback.getObjectId());
|
||||
panel.getChoice(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getChoice(), callback.getObjectId());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -267,7 +305,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_PLAY_MANA", callback.getObjectId(), message);
|
||||
panel.playMana(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId());
|
||||
panel.playMana(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -277,7 +315,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_PLAY_XMANA", callback.getObjectId(), message);
|
||||
panel.playXMana(message.getGameView(), message.getOptions(), message.getMessage(), callback.getMessageId());
|
||||
panel.playXMana(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -287,8 +325,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_GET_AMOUNT", callback.getObjectId(), message);
|
||||
|
||||
panel.getAmount(message.getGameView(), message.getOptions(), message.getMin(), message.getMax(), message.getMessage());
|
||||
panel.getAmount(callback.getMessageId(), message.getGameView(), message.getOptions(), message.getMin(), message.getMax(), message.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -298,8 +335,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_GET_MULTI_AMOUNT", callback.getObjectId(), message);
|
||||
|
||||
panel.getMultiAmount(message.getMessages(), message.getGameView(), message.getOptions(), message.getMin(), message.getMax());
|
||||
panel.getMultiAmount(callback.getMessageId(), message.getGameView(), message.getMessages(), message.getOptions(), message.getMin(), message.getMax());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -308,7 +344,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData());
|
||||
panel.updateGame((GameView) callback.getData(), true, null, null); // update after undo wtf?!
|
||||
panel.updateGame(callback.getMessageId(), (GameView) callback.getData(), true, null, null); // update after undo wtf?! // TODO: clean dialogs?!
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -336,21 +372,13 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
break;
|
||||
}
|
||||
|
||||
case GAME_INFORM: {
|
||||
if (callback.getMessageId() > gameInformMessageId) {
|
||||
{
|
||||
case GAME_UPDATE_AND_INFORM: {
|
||||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_INFORM", callback.getObjectId(), message);
|
||||
panel.inform(message.getMessage(), message.getGameView(), callback.getMessageId());
|
||||
panel.inform(callback.getMessageId(), message.getGameView(), message.getMessage());
|
||||
}
|
||||
}
|
||||
// no longer needed because phase skip handling on server side now
|
||||
} else {
|
||||
logger.warn(new StringBuilder("message out of sequence - ignoring").append("MessageId = ").append(callback.getMessageId()).append(" method = ").append(callback.getMethod()));
|
||||
}
|
||||
gameInformMessageId = messageId;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -432,14 +460,10 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
}
|
||||
|
||||
default: {
|
||||
// TODO: add exception here and process miss events like TOURNAMENT_UPDATE
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// sync message for server side events only
|
||||
if (!callback.getMethod().isClientSideMessage()) {
|
||||
messageId = callback.getMessageId();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
handleException(ex);
|
||||
}
|
||||
|
|
@ -539,7 +563,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
}
|
||||
}
|
||||
|
||||
protected void gameStarted(final UUID gameId, final UUID playerId) {
|
||||
protected void gameStarted(final int messageId, final UUID gameId, final UUID playerId) {
|
||||
try {
|
||||
frame.showGame(gameId, playerId);
|
||||
logger.info("Game " + gameId + " started for player " + playerId);
|
||||
|
|
@ -552,7 +576,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
}
|
||||
}
|
||||
|
||||
protected void draftStarted(UUID draftId, UUID playerId) {
|
||||
protected void draftStarted(int messageId, UUID draftId, UUID playerId) {
|
||||
try {
|
||||
frame.showDraft(draftId);
|
||||
logger.info("Draft " + draftId + " started for player " + playerId);
|
||||
|
|
@ -561,7 +585,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
}
|
||||
}
|
||||
|
||||
protected void tournamentStarted(UUID tournamentId, UUID playerId) {
|
||||
protected void tournamentStarted(int messageId, UUID tournamentId, UUID playerId) {
|
||||
try {
|
||||
frame.showTournament(tournamentId);
|
||||
AudioManager.playTournamentStarted();
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ public class NewPlayerPanel extends javax.swing.JPanel {
|
|||
|
||||
lblLevel.setText("Skill:");
|
||||
|
||||
spnLevel.setModel(new javax.swing.SpinnerNumberModel(6, 1, 10, 1));
|
||||
spnLevel.setModel(new javax.swing.SpinnerNumberModel(2, 1, 10, 1));
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public class TournamentPlayerPanel extends javax.swing.JPanel {
|
|||
|
||||
jLabel3.setText("Skill:");
|
||||
|
||||
spnLevel.setModel(new javax.swing.SpinnerNumberModel(6, 1, 10, 1));
|
||||
spnLevel.setModel(new javax.swing.SpinnerNumberModel(2, 1, 10, 1));
|
||||
spnLevel.setRequestFocusEnabled(false);
|
||||
|
||||
javax.swing.GroupLayout pnlPlayerNameLayout = new javax.swing.GroupLayout(pnlPlayerName);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* TODO: part of replay system? Un-used, can be deleted
|
||||
*
|
||||
* Utility class to save an object on disk.
|
||||
*
|
||||
* @author ayrat
|
||||
|
|
|
|||
|
|
@ -6,14 +6,13 @@ import mage.client.constants.Constants;
|
|||
import mage.constants.Rarity;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static org.mage.plugins.card.dl.DownloadJob.fromURL;
|
||||
import static org.mage.plugins.card.dl.DownloadJob.toFile;
|
||||
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* WARNING, unsupported images plugin, last updates from 2018
|
||||
*/
|
||||
|
|
@ -103,7 +102,8 @@ public class GathererSets implements Iterable<DownloadJob> {
|
|||
"C21","MH2","AFR","AFC","J21","MID","MIC","VOW","VOC","YMID",
|
||||
"NEC","NEO","SNC","NCC","CLB","2X2","DMU","DMC","40K","GN3",
|
||||
"UNF","BRO","BRC","BOT","30A","J22","SCD","DMR","ONE","ONC",
|
||||
"MOM","MOC","MUL","MAT","LTR","CMM","WOE","WHO","RVR","WOT","WOC"
|
||||
"MOM","MOC","MUL","MAT","LTR","CMM","WOE","WHO","RVR","WOT",
|
||||
"WOC","SPG","LCI","LCC","REX"
|
||||
// "HHO", "ANA" -- do not exist on gatherer
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -533,6 +533,13 @@ public class ScryfallImageSupportCards {
|
|||
add("WOE"); // Wilds of Eldraine
|
||||
add("WOT"); // Wilds of Eldraine: Enchanting Tales
|
||||
add("WOC"); // Wilds of Eldraine Commander
|
||||
add("LCI"); // Lost Caverns of Ixalan
|
||||
add("LCC"); // Lost Caverns of Ixalan Commander
|
||||
add("REX"); // Jurassic World Collection
|
||||
add("SPG"); // Special Guests
|
||||
|
||||
// Custom sets using Scryfall images - must provide a direct link for each card in directDownloadLinks
|
||||
add("CALC"); // Custom Alchemized versions of existing cards
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -999,6 +1006,9 @@ public class ScryfallImageSupportCards {
|
|||
put("PMEI/Jamuraan Lion/10*", "https://api.scryfall.com/cards/pmei/10★/");
|
||||
// PRES
|
||||
put("PRES/Lathliss, Dragon Queen/149*", "https://api.scryfall.com/cards/pres/149★/");
|
||||
|
||||
// CALC -- custom alchemy version of cards.
|
||||
put("CALC/C-Pillar of the Paruns", "https://api.scryfall.com/cards/dis/176/");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mage.interfaces.callback;
|
|||
|
||||
import mage.remote.traffic.ZippedObject;
|
||||
import mage.utils.CompressUtil;
|
||||
import mage.utils.ThreadUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
|
@ -11,11 +12,23 @@ import java.util.UUID;
|
|||
*/
|
||||
public class ClientCallback implements Serializable {
|
||||
|
||||
// for debug only: simulate bad connection on client side, use launcher's client param like -Dxmage.badconnection
|
||||
private static final String SIMULATE_BAD_CONNECTION_PROP = "xmage.badconnection";
|
||||
public static final boolean SIMULATE_BAD_CONNECTION;
|
||||
|
||||
static {
|
||||
SIMULATE_BAD_CONNECTION = System.getProperty(SIMULATE_BAD_CONNECTION_PROP) != null;
|
||||
}
|
||||
|
||||
private UUID objectId;
|
||||
private Object data;
|
||||
private ClientCallbackMethod method;
|
||||
private int messageId;
|
||||
|
||||
public ClientCallback(ClientCallbackMethod method, UUID objectId) {
|
||||
this(method, objectId, null);
|
||||
}
|
||||
|
||||
public ClientCallback(ClientCallbackMethod method, UUID objectId, Object data) {
|
||||
this(method, objectId, data, true);
|
||||
}
|
||||
|
|
@ -26,8 +39,10 @@ public class ClientCallback implements Serializable {
|
|||
this.setData(data, useCompress);
|
||||
}
|
||||
|
||||
public ClientCallback(ClientCallbackMethod method, UUID objectId) {
|
||||
this(method, objectId, null);
|
||||
private void simulateBadConnection() {
|
||||
if (SIMULATE_BAD_CONNECTION) {
|
||||
ThreadUtils.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
|
@ -55,12 +70,14 @@ public class ClientCallback implements Serializable {
|
|||
this.data = data;
|
||||
} else {
|
||||
this.data = CompressUtil.compress(data);
|
||||
simulateBadConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public void decompressData() {
|
||||
if (this.data instanceof ZippedObject) {
|
||||
this.data = CompressUtil.decompress(this.data);
|
||||
simulateBadConnection();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,68 +1,86 @@
|
|||
package mage.interfaces.callback;
|
||||
|
||||
/**
|
||||
* Created by IGOUDT on 4-4-2017.
|
||||
* Server's commands to process on client side. Commands can come in un-synced state due bad/slow network
|
||||
* <p>
|
||||
* Can be:
|
||||
* - critical events (messages, game events, choose dialogs, etc)
|
||||
* - non-critical events (game updates, messages)
|
||||
*/
|
||||
public enum ClientCallbackMethod {
|
||||
|
||||
CHATMESSAGE("chatMessage"),
|
||||
TOURNAMENT_INIT("tournamentInit"),
|
||||
TOURNAMENT_UPDATE("tournamentUpdate"),
|
||||
TOURNAMENT_OVER("tournamentOver"),
|
||||
JOINED_TABLE("joinedTable"),
|
||||
START_DRAFT("startDraft"),
|
||||
START_TOURNAMENT("startTournament"),
|
||||
SIDEBOARD("sideboard"),
|
||||
VIEW_LIMITED_DECK("viewLimitedDeck"),
|
||||
VIEW_SIDEBOARD("viewSideboard"),
|
||||
CONSTRUCT("construct"),
|
||||
SHOW_USERMESSAGE("showUserMessage"),
|
||||
WATCHGAME("watchGame"),
|
||||
REPLAY_GAME("replayGame"),
|
||||
START_GAME("startGame"),
|
||||
SHOW_TOURNAMENT("showTournament"),
|
||||
SHOW_GAME_END_DIALOG("showGameEndDialog"),
|
||||
SERVER_MESSAGE("serverMessage"),
|
||||
GAME_INIT("gameInit"),
|
||||
GAME_OVER("gameOver"),
|
||||
GAME_INFORM("gameInform"),
|
||||
GAME_INFORM_PERSONAL("gameInformPersonal"),
|
||||
GAME_ERROR("gameError"),
|
||||
GAME_UPDATE("gameUpdate"),
|
||||
GAME_REDRAW_GUI("gameRedrawGUI", true),
|
||||
DRAFT_OVER("draftOver"),
|
||||
REPLAY_DONE("replayDone"),
|
||||
USER_REQUEST_DIALOG("userRequestDialog"),
|
||||
REPLAY_UPDATE("replayUpdate"),
|
||||
REPLAY_INIT("replayInit"),
|
||||
END_GAME_INFO("endGameInfo"),
|
||||
GAME_TARGET("gameTarget"),
|
||||
GAME_CHOOSE_ABILITY("gameChooseAbility"),
|
||||
GAME_CHOOSE_PILE("gameChoosePile"),
|
||||
GAME_CHOOSE_CHOICE("gameChooseChoice"),
|
||||
GAME_ASK("gameAsk"),
|
||||
GAME_SELECT("gameSelect"),
|
||||
GAME_PLAY_MANA("gamePlayMana"),
|
||||
GAME_PLAY_XMANA("gamePlayXMana"),
|
||||
GAME_GET_AMOUNT("gameSelectAmount"),
|
||||
GAME_GET_MULTI_AMOUNT("gameSelectMultiAmount"),
|
||||
DRAFT_INIT("draftInit"),
|
||||
DRAFT_PICK("draftPick"),
|
||||
DRAFT_UPDATE("draftUpdate");
|
||||
// TODO: rename events due place/action like GAME_STARTED, GAME_ASK_DIALOG, GAME_TARGET_DIALOG
|
||||
|
||||
String code;
|
||||
boolean isClientSideMessage;
|
||||
// messages
|
||||
CHATMESSAGE(ClientCallbackType.MESSAGE, "chatMessage"),
|
||||
SHOW_USERMESSAGE(ClientCallbackType.MESSAGE, "showUserMessage"),
|
||||
SERVER_MESSAGE(ClientCallbackType.MESSAGE, "serverMessage"),
|
||||
|
||||
ClientCallbackMethod(String code) {
|
||||
this(code, false);
|
||||
}
|
||||
// table
|
||||
JOINED_TABLE(ClientCallbackType.TABLE_CHANGE, "joinedTable"),
|
||||
|
||||
ClientCallbackMethod(String code, boolean isClientSideMessage) {
|
||||
// tournament
|
||||
START_TOURNAMENT(ClientCallbackType.TABLE_CHANGE, "startTournament"),
|
||||
TOURNAMENT_INIT(ClientCallbackType.TABLE_CHANGE, "tournamentInit"), // TODO: unused on client
|
||||
TOURNAMENT_UPDATE(ClientCallbackType.UPDATE, "tournamentUpdate"), // TODO: unused on client
|
||||
TOURNAMENT_OVER(ClientCallbackType.TABLE_CHANGE, "tournamentOver"), // TODO: unused on client
|
||||
|
||||
// draft/sideboard
|
||||
START_DRAFT(ClientCallbackType.TABLE_CHANGE, "startDraft"),
|
||||
SIDEBOARD(ClientCallbackType.TABLE_CHANGE, "sideboard"),
|
||||
CONSTRUCT(ClientCallbackType.TABLE_CHANGE, "construct"),
|
||||
DRAFT_OVER(ClientCallbackType.TABLE_CHANGE, "draftOver"),
|
||||
DRAFT_INIT(ClientCallbackType.TABLE_CHANGE, "draftInit"),
|
||||
DRAFT_PICK(ClientCallbackType.TABLE_CHANGE, "draftPick"),
|
||||
DRAFT_UPDATE(ClientCallbackType.UPDATE, "draftUpdate"),
|
||||
|
||||
// watch
|
||||
SHOW_TOURNAMENT(ClientCallbackType.TABLE_CHANGE, "showTournament"),
|
||||
WATCHGAME(ClientCallbackType.TABLE_CHANGE, "watchGame"),
|
||||
|
||||
// in-game actions
|
||||
VIEW_LIMITED_DECK(ClientCallbackType.MESSAGE, "viewLimitedDeck"),
|
||||
VIEW_SIDEBOARD(ClientCallbackType.MESSAGE, "viewSideboard"),
|
||||
|
||||
// other
|
||||
USER_REQUEST_DIALOG(ClientCallbackType.DIALOG, "userRequestDialog"),
|
||||
GAME_REDRAW_GUI(ClientCallbackType.CLIENT_SIDE_EVENT, "gameRedrawGUI"),
|
||||
|
||||
// game
|
||||
START_GAME(ClientCallbackType.TABLE_CHANGE, "startGame"),
|
||||
GAME_INIT(ClientCallbackType.TABLE_CHANGE, "gameInit"),
|
||||
GAME_UPDATE_AND_INFORM(ClientCallbackType.UPDATE, "gameInform"), // update game and feedback panel with current status (e.g. on non our priority)
|
||||
GAME_INFORM_PERSONAL(ClientCallbackType.MESSAGE, "gameInformPersonal"),
|
||||
GAME_ERROR(ClientCallbackType.MESSAGE, "gameError"),
|
||||
GAME_UPDATE(ClientCallbackType.UPDATE, "gameUpdate"),
|
||||
GAME_TARGET(ClientCallbackType.DIALOG, "gameTarget"),
|
||||
GAME_CHOOSE_ABILITY(ClientCallbackType.DIALOG, "gameChooseAbility"),
|
||||
GAME_CHOOSE_PILE(ClientCallbackType.DIALOG, "gameChoosePile"),
|
||||
GAME_CHOOSE_CHOICE(ClientCallbackType.DIALOG, "gameChooseChoice"),
|
||||
GAME_ASK(ClientCallbackType.DIALOG, "gameAsk"),
|
||||
GAME_SELECT(ClientCallbackType.DIALOG, "gameSelect"),
|
||||
GAME_PLAY_MANA(ClientCallbackType.DIALOG, "gamePlayMana"),
|
||||
GAME_PLAY_XMANA(ClientCallbackType.DIALOG, "gamePlayXMana"),
|
||||
GAME_GET_AMOUNT(ClientCallbackType.DIALOG, "gameSelectAmount"),
|
||||
GAME_GET_MULTI_AMOUNT(ClientCallbackType.DIALOG, "gameSelectMultiAmount"),
|
||||
GAME_OVER(ClientCallbackType.TABLE_CHANGE, "gameOver"),
|
||||
END_GAME_INFO(ClientCallbackType.TABLE_CHANGE, "endGameInfo"),
|
||||
|
||||
// replay (unsupported)
|
||||
REPLAY_GAME(ClientCallbackType.TABLE_CHANGE, "replayGame"),
|
||||
REPLAY_INIT(ClientCallbackType.TABLE_CHANGE, "replayInit"),
|
||||
REPLAY_UPDATE(ClientCallbackType.UPDATE, "replayUpdate"),
|
||||
REPLAY_DONE(ClientCallbackType.TABLE_CHANGE, "replayDone");
|
||||
|
||||
final ClientCallbackType type;
|
||||
final String code;
|
||||
|
||||
ClientCallbackMethod(ClientCallbackType type, String code) {
|
||||
this.type = type;
|
||||
this.code = code;
|
||||
this.isClientSideMessage = isClientSideMessage;
|
||||
}
|
||||
|
||||
public boolean isClientSideMessage() {
|
||||
return this.isClientSideMessage;
|
||||
public ClientCallbackType getType() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package mage.interfaces.callback;
|
||||
|
||||
/**
|
||||
* Server event type for processing on the client
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public enum ClientCallbackType {
|
||||
|
||||
UPDATE(true, true), // game update
|
||||
TABLE_CHANGE, // all important game events + game update
|
||||
MESSAGE(true, false), // show message/log without game update
|
||||
DIALOG, // all dialogs + game update
|
||||
CLIENT_SIDE_EVENT(true, true); // without game uodate
|
||||
|
||||
final boolean canComeInAnyOrder;
|
||||
final boolean mustIgnoreOnOutdated; // if event come in any order and contain game update then it must be ignored on outdate
|
||||
|
||||
ClientCallbackType() {
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
ClientCallbackType(boolean canComeInAnyOrder, boolean mustIgnoreOnOutdated) {
|
||||
this.canComeInAnyOrder = canComeInAnyOrder;
|
||||
this.mustIgnoreOnOutdated = mustIgnoreOnOutdated;
|
||||
}
|
||||
|
||||
public boolean canComeInAnyOrder() {
|
||||
return this.canComeInAnyOrder;
|
||||
}
|
||||
|
||||
public boolean mustIgnoreOnOutdated() {
|
||||
return this.mustIgnoreOnOutdated;
|
||||
}
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ public class GameView implements Serializable {
|
|||
private final int turn;
|
||||
private boolean special = false;
|
||||
private final boolean isPlayer; // false = watching user
|
||||
private final int spellsCastCurrentTurn;
|
||||
private final boolean rollbackTurnsAllowed;
|
||||
|
||||
public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) {
|
||||
|
|
@ -195,13 +194,6 @@ public class GameView implements Serializable {
|
|||
} else {
|
||||
this.special = false;
|
||||
}
|
||||
|
||||
CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
|
||||
if (watcher != null) {
|
||||
spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn();
|
||||
} else {
|
||||
spellsCastCurrentTurn = 0;
|
||||
}
|
||||
rollbackTurnsAllowed = game.getOptions().rollbackTurnsAllowed;
|
||||
}
|
||||
|
||||
|
|
@ -335,10 +327,6 @@ public class GameView implements Serializable {
|
|||
this.canPlayObjects = canPlayObjects;
|
||||
}
|
||||
|
||||
public int getSpellsCastCurrentTurn() {
|
||||
return spellsCastCurrentTurn;
|
||||
}
|
||||
|
||||
public boolean isRollbackTurnsAllowed() {
|
||||
return rollbackTurnsAllowed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public class Modern extends Constructed {
|
|||
banned.add("Tree of Tales");
|
||||
banned.add("Umezawa's Jitte");
|
||||
banned.add("Uro, Titan of Nature's Wrath");
|
||||
banned.add("Yorion, the Sky Nomad");
|
||||
banned.add("Yorion, Sky Nomad");
|
||||
banned.add("Vault of Whispers");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ import java.util.UUID;
|
|||
* To summarize, this uses the default rules for a 1v1 limited match,
|
||||
* with two additional custom rules: <p>
|
||||
* -> At the beginning of each player's first main phase, that player
|
||||
* conjure into play a Pillar of the Paruns. This does count as a
|
||||
* land drop for the turn. <p>
|
||||
* -> The starting hand size is 6, not 7.
|
||||
* conjure into play a custom version of Pillar of the Paruns. This
|
||||
* does count as a land drop for the turn. The custom Pillar has
|
||||
* hexproof and gain "{T}: add {1}."<p>
|
||||
* -> The starting hand size is 6, and the starting life count is 25.
|
||||
* <p> <p>
|
||||
* I did took the inspiration for the mode from this cube list (not
|
||||
* sure it is the original source for the idea, but i did not found
|
||||
|
|
@ -49,7 +50,7 @@ import java.util.UUID;
|
|||
public class CustomPillarOfTheParunsDuel extends GameImpl {
|
||||
|
||||
public CustomPillarOfTheParunsDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan) {
|
||||
super(attackOption, range, mulligan, 20, 40, 6);
|
||||
super(attackOption, range, mulligan, 25, 40, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -57,7 +58,10 @@ public class CustomPillarOfTheParunsDuel extends GameImpl {
|
|||
super.init(choosingPlayerId);
|
||||
|
||||
getPlayers().forEach((playerId, p) -> {
|
||||
addDelayedTriggeredAbility(new AtTheBeginOfPlayerFirstMainPhase(playerId, "Pillar of the Paruns"), null);
|
||||
addDelayedTriggeredAbility(
|
||||
new AtTheBeginOfPlayerFirstMainPhase(playerId, "C-Pillar of the Paruns"),
|
||||
null // TODO: Not sure how to mock something to be displayed instead.
|
||||
);
|
||||
});
|
||||
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId).withSkipStep(PhaseStep.DRAW));
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
|
||||
private static final boolean ALLOW_USERS_TO_PUT_NON_PLAYABLE_SPELLS_ON_STACK_WORKAROUND = false; // warning, see workaround's info on usage
|
||||
|
||||
// TODO: all user feedback actions executed and waited in diff threads and can't catch exeptions, e.g. on wrong code usage
|
||||
// must catch and log such errors
|
||||
private transient Boolean responseOpenedForAnswer = false; // can't get response until prepared target (e.g. until send all fire events to all players)
|
||||
private final transient PlayerResponse response = new PlayerResponse();
|
||||
|
||||
|
|
@ -1315,7 +1317,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
while (canRespond()) {
|
||||
// try to set trigger auto order
|
||||
java.util.List<TriggeredAbility> abilitiesWithNoOrderSet = new ArrayList<>();
|
||||
TriggeredAbility abilityOrderLast = null;
|
||||
java.util.List<TriggeredAbility> abilitiesOrderLast = new ArrayList<>();
|
||||
for (TriggeredAbility ability : abilities) {
|
||||
if (triggerAutoOrderAbilityFirst.contains(ability.getOriginalId())) {
|
||||
return ability;
|
||||
|
|
@ -1326,17 +1328,20 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return ability;
|
||||
}
|
||||
if (triggerAutoOrderAbilityLast.contains(ability.getOriginalId())) {
|
||||
abilityOrderLast = ability;
|
||||
// multiple instances of same trigger has same originalId, no need to select order for it
|
||||
abilitiesOrderLast.add(ability);
|
||||
continue;
|
||||
}
|
||||
if (triggerAutoOrderNameLast.contains(rule)) {
|
||||
abilityOrderLast = ability;
|
||||
abilitiesOrderLast.add(ability);
|
||||
continue;
|
||||
}
|
||||
if (autoOrderUse) {
|
||||
// multiple triggers with same rule text will be auto-ordered
|
||||
if (autoOrderRuleText == null) {
|
||||
autoOrderRuleText = rule;
|
||||
} else if (!rule.equals(autoOrderRuleText)) {
|
||||
// diff triggers, so must use choose dialog
|
||||
autoOrderUse = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1344,7 +1349,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
|
||||
if (abilitiesWithNoOrderSet.isEmpty()) {
|
||||
return abilityOrderLast;
|
||||
// user can send diff abilities to the last, will be selected by "first" like first ordered ability above
|
||||
return abilitiesOrderLast.stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
if (abilitiesWithNoOrderSet.size() == 1
|
||||
|
|
@ -1352,6 +1358,21 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return abilitiesWithNoOrderSet.iterator().next();
|
||||
}
|
||||
|
||||
// runtime check: lost triggers for GUI
|
||||
List<Ability> processingAbilities = new ArrayList<>(abilitiesWithNoOrderSet);
|
||||
processingAbilities.addAll(abilitiesOrderLast);
|
||||
|
||||
if (abilities.size() != processingAbilities.size()) {
|
||||
throw new IllegalStateException(String.format("Choose dialog lost some of the triggered abilities:\n"
|
||||
+ "Must %d:\n%s\n"
|
||||
+ "Has %d:\n%s",
|
||||
abilities.size(),
|
||||
abilities.stream().map(Ability::getRule).collect(Collectors.joining("\n")),
|
||||
processingAbilities.size(),
|
||||
processingAbilities.stream().map(Ability::getRule).collect(Collectors.joining("\n"))
|
||||
));
|
||||
}
|
||||
|
||||
macroTriggeredSelectionFlag = true;
|
||||
updateGameStatePriority("chooseTriggeredAbility", game);
|
||||
prepareForResponse(game);
|
||||
|
|
@ -2662,6 +2683,13 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GUI related, remember choices for choose trigger dialog
|
||||
*
|
||||
* @param playerAction
|
||||
* @param game
|
||||
* @param data
|
||||
*/
|
||||
private void setTriggerAutoOrder(PlayerAction playerAction, Game game, Object data) {
|
||||
if (playerAction == TRIGGER_AUTO_ORDER_RESET_ALL) {
|
||||
triggerAutoOrderAbilityFirst.clear();
|
||||
|
|
@ -2670,7 +2698,9 @@ public class HumanPlayer extends PlayerImpl {
|
|||
triggerAutoOrderNameLast.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data instanceof UUID) {
|
||||
// remember by id
|
||||
UUID abilityId = (UUID) data;
|
||||
UUID originalId = null;
|
||||
for (TriggeredAbility ability : game.getState().getTriggered(getId())) {
|
||||
|
|
@ -2685,12 +2715,17 @@ public class HumanPlayer extends PlayerImpl {
|
|||
triggerAutoOrderAbilityFirst.add(originalId);
|
||||
break;
|
||||
case TRIGGER_AUTO_ORDER_ABILITY_LAST:
|
||||
triggerAutoOrderAbilityFirst.add(originalId);
|
||||
triggerAutoOrderAbilityLast.add(originalId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (data instanceof String) {
|
||||
// remember by name
|
||||
String abilityName = (String) data;
|
||||
if (abilityName.contains("{this}")) {
|
||||
throw new IllegalArgumentException("Wrong code usage. Remembering trigger must contains full rules name without {this}.");
|
||||
}
|
||||
|
||||
switch (playerAction) {
|
||||
case TRIGGER_AUTO_ORDER_NAME_FIRST:
|
||||
triggerAutoOrderNameFirst.add(abilityName);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -271,10 +271,6 @@ public class User {
|
|||
fireCallback(new ClientCallback(ClientCallbackMethod.SHOW_TOURNAMENT, tournamentId));
|
||||
}
|
||||
|
||||
public void ccShowGameEndDialog(final UUID gameId) {
|
||||
fireCallback(new ClientCallback(ClientCallbackMethod.SHOW_GAME_END_DIALOG, gameId));
|
||||
}
|
||||
|
||||
public void showUserMessage(final String titel, String message) {
|
||||
List<String> messageData = new LinkedList<>();
|
||||
messageData.add(titel);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public class GameSessionWatcher {
|
|||
|
||||
public void inform(final String message) {
|
||||
if (!killed) {
|
||||
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), null, message))));
|
||||
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_UPDATE_AND_INFORM, game.getId(), new GameClientMessage(getGameView(), null, message))));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,11 +61,6 @@ class AbeyanceEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new AbeyanceEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject mageObject = game.getObject(source);
|
||||
|
|
@ -76,6 +71,12 @@ class AbeyanceEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL
|
||||
|| event.getType() == GameEvent.EventType.ACTIVATE_ABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (source.getFirstTarget() != null
|
||||
|
|
|
|||
|
|
@ -57,11 +57,6 @@ class AetherStormReplacementEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AetherStormReplacementEffect copy() {
|
||||
return new AetherStormReplacementEffect(this);
|
||||
|
|
|
|||
|
|
@ -65,11 +65,6 @@ class AggressiveMiningEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new AggressiveMiningEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.PLAY_LAND;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
|
@ -88,11 +90,14 @@ class AgrusKosEternalSoldierTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (!event.getTargetId().equals(getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
StackObject stackObject = game.getStack().getStackObject(event.getSourceId());
|
||||
if (stackObject == null) {
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
if (targetingObject == null || targetingObject instanceof Spell) {
|
||||
return false;
|
||||
}
|
||||
Set<UUID> targets = stackObject
|
||||
if (CardUtil.checkTargetedEventAlreadyUsed(this.id.toString(), targetingObject, event, game)) {
|
||||
return false;
|
||||
}
|
||||
Set<UUID> targets = targetingObject
|
||||
.getStackAbility()
|
||||
.getTargets()
|
||||
.stream()
|
||||
|
|
@ -102,7 +107,7 @@ class AgrusKosEternalSoldierTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (targets.isEmpty() || !targets.stream().allMatch(getSourceId()::equals)) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setValue("triggeringAbility", stackObject);
|
||||
this.getEffects().setValue("triggeringAbility", targetingObject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
||||
import mage.abilities.effects.common.SacrificeEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -36,21 +37,12 @@ public class AllegiantGeneralPryde extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Trooper creatures you control have "When this creature enters the battlefield, you may sacrifice a creature. If you do, draw two cards and lose 2 life."
|
||||
SacrificeEffect sacrifceEffect = new SacrificeEffect(
|
||||
StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED, 1, "");
|
||||
EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(sacrifceEffect, true, true);
|
||||
ability.setTriggerPhrase("When this creature enters the battlefield, ");
|
||||
ability.addTarget(new TargetControlledCreaturePermanent(1));
|
||||
DrawCardSourceControllerEffect drawCardSourceControllerEffect = new DrawCardSourceControllerEffect(2);
|
||||
drawCardSourceControllerEffect.setText("If you do, draw two cards");
|
||||
ability.addEffect(drawCardSourceControllerEffect);
|
||||
LoseLifeSourceControllerEffect loseLifeSourceControllerEffect = new LoseLifeSourceControllerEffect(2);
|
||||
loseLifeSourceControllerEffect.setText("and lose 2 life.");
|
||||
ability.addEffect(loseLifeSourceControllerEffect);
|
||||
//EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(2), true);
|
||||
GainAbilityControlledEffect effect = new GainAbilityControlledEffect(
|
||||
ability, Duration.WhileOnBattlefield, filter);
|
||||
this.addAbility(new SimpleStaticAbility(effect));
|
||||
Ability gainedAbility = new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
|
||||
new DrawCardSourceControllerEffect(2),
|
||||
new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)
|
||||
).addEffect(new LoseLifeSourceControllerEffect(2).concatBy("and")))
|
||||
.setTriggerPhrase("When this creature enters the battlefield, ");
|
||||
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(gainedAbility, Duration.WhileOnBattlefield, filter)));
|
||||
}
|
||||
|
||||
private AllegiantGeneralPryde(final AllegiantGeneralPryde card) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.common.BecomesTargetControllerTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.TargetOfOpponentsSpellOrAbilityTriggeredAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||
|
|
@ -9,6 +9,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
|
|
@ -24,7 +25,8 @@ public final class AmuletOfSafekeeping extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
// Whenever you become the target of a spell or ability an opponent controls, counter that spell or ability unless its controller pays {1}.
|
||||
this.addAbility(new TargetOfOpponentsSpellOrAbilityTriggeredAbility(new CounterUnlessPaysEffect(new GenericManaCost(1)), false, true));
|
||||
this.addAbility(new BecomesTargetControllerTriggeredAbility(new CounterUnlessPaysEffect(new GenericManaCost(1)),
|
||||
null, StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS, SetTargetPointer.SPELL, false));
|
||||
|
||||
// Creature tokens get -1/-0.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ package mage.cards.a;
|
|||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
|
|
@ -21,11 +20,10 @@ import java.util.UUID;
|
|||
public final class AncientLumberknot extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter
|
||||
= new FilterCreaturePermanent("each creature you control with toughness greater than its power");
|
||||
= new FilterCreaturePermanent("creature you control with toughness greater than its power");
|
||||
|
||||
static {
|
||||
filter.add(AncientLumberknotPredicate.instance);
|
||||
filter.add(TargetController.YOU.getControllerPredicate());
|
||||
}
|
||||
|
||||
public AncientLumberknot(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
|
@ -36,7 +34,7 @@ public final class AncientLumberknot extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Each creature you control with toughness greater than its power assigns combat damage equal to its toughness rather than its power.
|
||||
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(filter)));
|
||||
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect(filter)));
|
||||
}
|
||||
|
||||
private AncientLumberknot(final AncientLumberknot card) {
|
||||
|
|
|
|||
|
|
@ -98,11 +98,6 @@ class AngelicArbiterEffect2 extends ContinuousRuleModifyingEffectImpl {
|
|||
return new AngelicArbiterEffect2(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BecomesTargetSourceFirstTimeTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
|
@ -12,18 +12,15 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.common.NumberOfTimesPermanentTargetedATurnWatcher;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author AustinYQM
|
||||
* @author AustinYQM, xenohedron
|
||||
*/
|
||||
public final class AngelicCub extends CardImpl {
|
||||
|
||||
|
|
@ -36,7 +33,11 @@ public final class AngelicCub extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Whenever Angelic Cub becomes the target of a spell or ability for the first time each turn, put a +1/+1 counter on it.
|
||||
this.addAbility(new AngelicCubAbility(), new NumberOfTimesPermanentTargetedATurnWatcher());
|
||||
this.addAbility(new BecomesTargetSourceFirstTimeTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance())
|
||||
.setText("put a +1/+1 counter on it"),
|
||||
StaticFilters.FILTER_SPELL_OR_ABILITY_A, SetTargetPointer.NONE, false
|
||||
));
|
||||
// As long as Angelic Cub has three or more +1/+1 counters on it, it has flying.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.P1P1, 3), "As long as {this} has three or more +1/+1 counters on it, it has flying.")));
|
||||
}
|
||||
|
|
@ -50,41 +51,3 @@ public final class AngelicCub extends CardImpl {
|
|||
return new AngelicCub(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AngelicCubAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public AngelicCubAbility() {
|
||||
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false);
|
||||
}
|
||||
|
||||
public AngelicCubAbility(final mage.cards.a.AngelicCubAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public mage.cards.a.AngelicCubAbility copy() {
|
||||
return new mage.cards.a.AngelicCubAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getTargetId().equals(this.getSourceId())) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && permanent.isCreature(game)) {
|
||||
NumberOfTimesPermanentTargetedATurnWatcher watcher = game.getState().getWatcher(NumberOfTimesPermanentTargetedATurnWatcher.class);
|
||||
return watcher != null && watcher.notMoreThanOnceTargetedThisTurn(permanent, game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} becomes the target of a spell or ability for the first time each turn, put a +1/+1 counter on it.";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SourceBecomesTargetTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -25,9 +25,9 @@ public final class AngelicProtector extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
this.addAbility(new SourceBecomesTargetTriggeredAbility(
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(
|
||||
new BoostSourceEffect(0, 3, Duration.EndOfTurn)
|
||||
).setTriggerPhrase("Whenever {this} becomes the target of a spell or ability, "));
|
||||
).withRuleTextReplacement(false));
|
||||
}
|
||||
|
||||
private AngelicProtector(final AngelicProtector card) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
|
@ -14,7 +16,7 @@ import mage.constants.CardType;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.card.ExpansionSetPredicate;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.predicate.permanent.TokenPredicate;
|
||||
|
||||
/**
|
||||
|
|
@ -26,10 +28,14 @@ public final class ApocalypseChime extends CardImpl {
|
|||
private static final FilterPermanent filter = new FilterPermanent("nontoken permanents with a name originally printed in the Homelands expansion");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.and(
|
||||
TokenPredicate.FALSE,
|
||||
new ExpansionSetPredicate("HML")
|
||||
));
|
||||
// Homelands names per CR 206.3c
|
||||
List<String> nameStrings = Arrays.asList("Abbey Gargoyles", "Abbey Matron", "Aether Storm", "Aliban's Tower", "Ambush", "Ambush Party", "Anaba Ancestor", "Anaba Bodyguard", "Anaba Shaman", "Anaba Spirit Crafter", "An-Havva Constable", "An-Havva Inn", "An-Havva Township", "An-Zerrin Ruins", "Apocalypse Chime", "Autumn Willow", "Aysen Abbey", "Aysen Bureaucrats", "Aysen Crusader", "Aysen Highway", "Baki's Curse", "Baron Sengir", "Beast Walkers", "Black Carriage", "Broken Visage", "Carapace", "Castle Sengir", "Cemetery Gate", "Chain Stasis", "Chandler", "Clockwork Gnomes", "Clockwork Steed", "Clockwork Swarm", "Coral Reef", "Dark Maze", "Daughter of Autumn", "Death Speakers", "Didgeridoo", "Drudge Spell", "Dry Spell", "Dwarven Pony", "Dwarven Sea Clan", "Dwarven Trader", "Ebony Rhino", "Eron the Relentless", "Evaporate", "Faerie Noble", "Feast of the Unicorn", "Feroz's Ban", "Folk of An-Havva", "Forget", "Funeral March", "Ghost Hounds", "Giant Albatross", "Giant Oyster", "Grandmother Sengir", "Greater Werewolf", "Hazduhr the Abbot", "Headstone", "Heart Wolf", "Hungry Mist", "Ihsan's Shade", "Irini Sengir", "Ironclaw Curse", "Jinx", "Joven", "Joven's Ferrets", "Joven's Tools", "Koskun Falls", "Koskun Keep", "Labyrinth Minotaur", "Leaping Lizard", "Leeches", "Mammoth Harness", "Marjhan", "Memory Lapse", "Merchant Scroll", "Mesa Falcon", "Mystic Decree", "Narwhal", "Orcish Mine", "Primal Order", "Prophecy", "Rashka the Slayer", "Reef Pirates", "Renewal", "Retribution", "Reveka, Wizard Savant", "Root Spider", "Roots", "Roterothopter", "Rysorian Badger", "Samite Alchemist", "Sea Sprite", "Sea Troll", "Sengir Autocrat", "Sengir Bats", "Serra Aviary", "Serra Bestiary", "Serra Inquisitors", "Serra Paladin", "Serrated Arrows", "Shrink", "Soraya the Falconer", "Spectral Bears", "Timmerian Fiends", "Torture", "Trade Caravan", "Truce", "Veldrane of Sengir", "Wall of Kelp", "Willow Faerie", "Willow Priestess", "Winter Sky", "Wizards' School");
|
||||
List<NamePredicate> namePredicates = new ArrayList<>();
|
||||
for (String name: nameStrings) {
|
||||
namePredicates.add(new NamePredicate(name));
|
||||
}
|
||||
filter.add(TokenPredicate.FALSE);
|
||||
filter.add(Predicates.or(namePredicates));
|
||||
}
|
||||
|
||||
public ApocalypseChime(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
|
|
|||
72
Mage.Sets/src/mage/cards/a/ArborealAlliance.java
Normal file
72
Mage.Sets/src/mage/cards/a/ArborealAlliance.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.PopulateEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.SylvanOfferingTreefolkToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class ArborealAlliance extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent(SubType.ELF, "Elves");
|
||||
|
||||
public ArborealAlliance(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{X}{G}{G}");
|
||||
|
||||
// When Arboreal Alliance enters the battlefield, create an X/X green Treefolk creature token.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ArborealAllianceEffect()));
|
||||
|
||||
// Whenever you attack with one or more Elves, populate.
|
||||
this.addAbility(new AttacksWithCreaturesTriggeredAbility(
|
||||
new PopulateEffect(), 1, filter
|
||||
));
|
||||
}
|
||||
|
||||
private ArborealAlliance(final ArborealAlliance card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArborealAlliance copy() {
|
||||
return new ArborealAlliance(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ArborealAllianceEffect extends OneShotEffect {
|
||||
|
||||
ArborealAllianceEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
staticText = "create an X/X green Treefolk creature token";
|
||||
}
|
||||
|
||||
private ArborealAllianceEffect(final ArborealAllianceEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArborealAllianceEffect copy() {
|
||||
return new ArborealAllianceEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return new CreateTokenEffect(
|
||||
new SylvanOfferingTreefolkToken(ManacostVariableValue.ETB.calculate(game, source, this))
|
||||
).apply(game, source);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderAllEffect;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
|
||||
import mage.abilities.keyword.DefenderAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
|
|
@ -25,12 +25,10 @@ import java.util.UUID;
|
|||
public final class ArcadesTheStrategist extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent defenderSingle = new FilterControlledCreaturePermanent("a creature with defender");
|
||||
private static final FilterCreaturePermanent defenderPlural = new FilterCreaturePermanent("Each creature you control with defender");
|
||||
private static final FilterCreaturePermanent defenderPlural = new FilterCreaturePermanent("creature you control with defender");
|
||||
|
||||
static {
|
||||
defenderSingle.add(new AbilityPredicate(DefenderAbility.class));
|
||||
|
||||
defenderPlural.add(TargetController.YOU.getControllerPredicate());
|
||||
defenderPlural.add(new AbilityPredicate(DefenderAbility.class));
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +53,7 @@ public final class ArcadesTheStrategist extends CardImpl {
|
|||
));
|
||||
|
||||
// Each creature you control with defender assigns combat damage equal to its toughness rather than its power and can attack as though it didn't have defender.
|
||||
Ability ability = new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(defenderPlural));
|
||||
Ability ability = new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect(defenderPlural));
|
||||
ability.addEffect(new CanAttackAsThoughItDidntHaveDefenderAllEffect(
|
||||
Duration.WhileOnBattlefield, defenderSingle
|
||||
).setText("and can attack as though it didn't have defender"));
|
||||
|
|
|
|||
|
|
@ -1,25 +1,19 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -35,7 +29,6 @@ public final class AshenmoorLiege extends CardImpl {
|
|||
filterRedCreature.add(new ColorPredicate(ObjectColor.RED));
|
||||
}
|
||||
|
||||
|
||||
public AshenmoorLiege(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B/R}{B/R}{B/R}");
|
||||
this.subtype.add(SubType.ELEMENTAL);
|
||||
|
|
@ -50,10 +43,8 @@ public final class AshenmoorLiege extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filterRedCreature, true)));
|
||||
|
||||
// Whenever Ashenmoor Liege becomes the target of a spell or ability an opponent controls, that player loses 4 life.
|
||||
this.addAbility(new AshenmoorLiegeTriggeredAbility());
|
||||
|
||||
|
||||
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(new LoseLifeTargetEffect(4),
|
||||
StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS, SetTargetPointer.PLAYER, false));
|
||||
}
|
||||
|
||||
private AshenmoorLiege(final AshenmoorLiege card) {
|
||||
|
|
@ -65,39 +56,3 @@ public final class AshenmoorLiege extends CardImpl {
|
|||
return new AshenmoorLiege(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AshenmoorLiegeTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public AshenmoorLiegeTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(4), false);
|
||||
}
|
||||
|
||||
private AshenmoorLiegeTriggeredAbility(final AshenmoorLiegeTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AshenmoorLiegeTriggeredAbility copy() {
|
||||
return new AshenmoorLiegeTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getTargetId().equals(this.getSourceId()) && game.getOpponents(this.controllerId).contains(event.getPlayerId())) {
|
||||
getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} becomes the target of a spell or ability an opponent controls, that player loses 4 life.";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,11 +59,6 @@ class AshesOfTheAbhorrentEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new AshesOfTheAbhorrentEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL
|
||||
|
|
|
|||
|
|
@ -66,11 +66,6 @@ class AshiokDreamRenderEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new AshiokDreamRenderEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject mageObject = game.getObject(source);
|
||||
|
|
|
|||
|
|
@ -151,11 +151,6 @@ class AshioksErasureReplacementEffect extends ContinuousRuleModifyingEffectImpl
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AshioksErasureReplacementEffect copy() {
|
||||
return new AshioksErasureReplacementEffect(this);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -7,14 +6,13 @@ import mage.abilities.common.SimpleStaticAbility;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
|
||||
import mage.abilities.keyword.DefenderAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
|
@ -36,7 +34,7 @@ public final class AssaultFormation extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
|
||||
|
||||
// Each creature you control assigns combat damage equal to its toughness rather than its power.
|
||||
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
|
||||
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
|
||||
|
||||
// {G}: Target creature with defender can attack this turn as though it didn't have defender.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CanAttackAsThoughItDidntHaveDefenderTargetEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{G}"));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
|
@ -25,8 +24,9 @@ import mage.game.permanent.Permanent;
|
|||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class AssaultSuit extends CardImpl {
|
||||
|
|
@ -81,25 +81,20 @@ public final class AssaultSuit extends CardImpl {
|
|||
return new AssaultSuitCantBeSacrificed(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
return "This creature can't be sacrificed.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.SACRIFICE_PERMANENT) {
|
||||
Permanent equipment = game.getPermanent(source.getSourceId());
|
||||
if (equipment != null) {
|
||||
return equipment.isAttachedTo(event.getTargetId());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return equipment != null && equipment.isAttachedTo(event.getTargetId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public final class AstralDragon extends CardImpl {
|
|||
false, null, 3, 3, true);
|
||||
effect.setText("create two tokens that are copies of target noncreature permanent, " +
|
||||
"except they're 3/3 Dragon creatures in addition to their other types, and they have flying");
|
||||
effect.setAdditionalSubType(SubType.DRAGON);
|
||||
effect.withAdditionalSubType(SubType.DRAGON);
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(effect);
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
this.addAbility(ability.withFlavorWord("Project Image"));
|
||||
|
|
|
|||
|
|
@ -133,11 +133,6 @@ class AureliasFuryCantCastEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new AureliasFuryCantCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject mageObject = game.getObject(source);
|
||||
|
|
@ -176,20 +171,25 @@ class AureliasFuryDamagedByWatcher extends Watcher {
|
|||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
MageObject obj = game.getObject(event.getSourceId());
|
||||
if (!(obj instanceof Spell) || !sourceId.equals(((Spell) obj).getSourceId())) {
|
||||
return;
|
||||
}
|
||||
switch (event.getType()) {
|
||||
case DAMAGED_PERMANENT:
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && permanent.isCreature(game)) {
|
||||
if (isOurSource(event, game) && permanent != null && permanent.isCreature(game)) {
|
||||
damagedCreatures.add(event.getTargetId());
|
||||
}
|
||||
return;
|
||||
break;
|
||||
case DAMAGED_PLAYER:
|
||||
if (isOurSource(event, game)) {
|
||||
damagedPlayers.add(event.getTargetId());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOurSource(GameEvent event, Game game) {
|
||||
// must call after event filter
|
||||
MageObject obj = game.getObject(event.getSourceId());
|
||||
return obj instanceof Spell && sourceId.equals(((Spell) obj).getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -106,11 +106,6 @@ class AzorTheLawbringerCantCastEffect extends ContinuousRuleModifyingEffectImpl
|
|||
return new AzorTheLawbringerCantCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject mageObject = game.getObject(source);
|
||||
|
|
@ -120,6 +115,11 @@ class AzorTheLawbringerCantCastEffect extends ContinuousRuleModifyingEffectImpl
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
UUID opponentId = getTargetPointer().getFirst(game, source);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -37,7 +36,7 @@ public final class BaldinCenturyHerdmaster extends CardImpl {
|
|||
|
||||
// As long as it's your turn, each creature assigns combat damage equal to its toughness rather than its power.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE),
|
||||
new CombatDamageByToughnessAllEffect(),
|
||||
MyTurnCondition.instance, "as long as it's your turn, each creature " +
|
||||
"assigns combat damage equal to its toughness rather than its power"
|
||||
)));
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public final class BallroomBrawlers extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Whenever Ballroom Brawlers attacks, Ballroom Brawlers and up to one other target creature you control each gain your choice of first strike or lifelink until end of turn.
|
||||
Ability ability = new AttacksTriggeredAbility(new BallroomBrawlersEffect()).setReplaceRuleText(false);
|
||||
Ability ability = new AttacksTriggeredAbility(new BallroomBrawlersEffect()).withRuleTextReplacement(false);
|
||||
ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,16 +124,12 @@ class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.COUNTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.COUNTER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card == null) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -65,11 +65,6 @@ class BartelRuneaxeEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return event.getType() == GameEvent.EventType.TARGET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
|
|
|
|||
|
|
@ -72,11 +72,6 @@ class BasandraBattleSeraphEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new BasandraBattleSeraphEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public final class BasilicaScreecher extends CardImpl {
|
|||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Extort (Whenever you cast a spell, you pay {WB}. If you do, each opponent loses 1 life and you gain that much life.)
|
||||
// Extort (Whenever you cast a spell, you may pay {WB}. If you do, each opponent loses 1 life and you gain that much life.)
|
||||
this.addAbility(new ExtortAbility());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.BecomesTargetOpponentAllTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetAnyTriggeredAbility;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.keyword.ForetellAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -28,8 +30,8 @@ public final class BattleMammoth extends CardImpl {
|
|||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Whenever a permanent you control becomes the target of a spell or ability an opponent controls, you may draw a card.
|
||||
this.addAbility(new BecomesTargetOpponentAllTriggeredAbility(
|
||||
new DrawCardSourceControllerEffect(1), true
|
||||
this.addAbility(new BecomesTargetAnyTriggeredAbility(new DrawCardSourceControllerEffect(1),
|
||||
StaticFilters.FILTER_CONTROLLED_A_PERMANENT, StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS, SetTargetPointer.NONE, true
|
||||
));
|
||||
|
||||
// Foretell {2}{G}{G}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
|
||||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
|
||||
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -25,7 +23,7 @@ public final class BelligerentBrontodon extends CardImpl {
|
|||
this.toughness = new MageInt(6);
|
||||
|
||||
// Each creature you control assigns combat damage equal to its toughness rather than its power.
|
||||
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
|
||||
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
|
||||
}
|
||||
|
||||
private BelligerentBrontodon(final BelligerentBrontodon card) {
|
||||
|
|
|
|||
|
|
@ -19,11 +19,7 @@ import mage.game.permanent.Permanent;
|
|||
import mage.players.Player;
|
||||
import mage.target.common.TargetLandPermanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
|
|
@ -110,22 +106,32 @@ class BenthicExplorersManaEffect extends ManaEffect {
|
|||
@Override
|
||||
public Mana produceMana(Game game, Ability source) {
|
||||
Mana mana = new Mana();
|
||||
if (game == null) { return mana; }
|
||||
|
||||
Choice choice = ManaType.getChoiceOfManaTypes(getManaTypes(game, source), false);
|
||||
if (choice.getChoices().isEmpty()) { return mana; }
|
||||
if (game == null) {
|
||||
return mana;
|
||||
}
|
||||
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return mana;
|
||||
}
|
||||
|
||||
Choice choice = ManaType.getChoiceOfManaTypes(getManaTypes(game, source), false);
|
||||
if (choice.getChoices().isEmpty()) {
|
||||
return mana;
|
||||
}
|
||||
|
||||
|
||||
if (choice.getChoices().size() == 1) {
|
||||
choice.setChoice(choice.getChoices().iterator().next());
|
||||
} else {
|
||||
if (player == null
|
||||
|| !player.choose(Outcome.Neutral, choice, game)) {
|
||||
if (!player.choose(Outcome.PutManaInPool, choice, game)) {
|
||||
return mana;
|
||||
}
|
||||
}
|
||||
|
||||
if (choice.getChoice() == null) { return mana; }
|
||||
if (choice.getChoice() == null) {
|
||||
return mana;
|
||||
}
|
||||
|
||||
switch (choice.getChoice()) {
|
||||
case "Black":
|
||||
|
|
@ -160,7 +166,9 @@ class BenthicExplorersManaEffect extends ManaEffect {
|
|||
List<UUID> untapped = (List<UUID>) game.getState()
|
||||
.getValue("UntapTargetCost" + source.getSourceId().toString());
|
||||
Permanent land = game.getPermanentOrLKIBattlefield(untapped.get(0));
|
||||
if (land == null) { return types; }
|
||||
if (land == null) {
|
||||
return types;
|
||||
}
|
||||
|
||||
Abilities<ActivatedManaAbilityImpl> mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
|
||||
for (ActivatedManaAbilityImpl ability : mana) {
|
||||
|
|
|
|||
|
|
@ -72,20 +72,20 @@ class BerserkReplacementEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.CAST_SPELL && event.getSourceId().equals(source.getSourceId())) {
|
||||
if (event.getSourceId().equals(source.getSourceId())) {
|
||||
CombatDamageStepStartedWatcher watcher = game.getState().getWatcher(CombatDamageStepStartedWatcher.class);
|
||||
return watcher == null || watcher.conditionMet();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BerserkReplacementEffect copy() {
|
||||
return new BerserkReplacementEffect(this);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class BindTheMonsterEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply (Game game, Ability source) {
|
||||
Permanent attachment = source.getSourcePermanentIfItStillExists(game);
|
||||
Permanent attachment = source.getSourcePermanentOrLKI(game);
|
||||
if (attachment != null) {
|
||||
Permanent creature = game.getPermanent(attachment.getAttachedTo());
|
||||
if (creature != null) {
|
||||
|
|
|
|||
|
|
@ -108,11 +108,6 @@ class BlindingBeamEffect2 extends ContinuousRuleModifyingEffectImpl {
|
|||
return new BlindingBeamEffect2(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInactive(Ability source, Game game) {
|
||||
// the PRE step part is directly after the UNTAP events for permanents
|
||||
|
|
|
|||
|
|
@ -79,9 +79,4 @@ class BloodFrenzyCastRestriction extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SourceBecomesTargetTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect;
|
||||
import mage.cards.AdventureCard;
|
||||
|
|
@ -28,11 +28,11 @@ public final class BonecrusherGiant extends AdventureCard {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// Whenever Bonecrusher Giant becomes the target of a spell, Bonecrusher Giant deals 2 damage to that spell's controller.
|
||||
this.addAbility(new SourceBecomesTargetTriggeredAbility(
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(
|
||||
new DamageTargetEffect(
|
||||
2, true, "that spell's controller", "{this}"
|
||||
), StaticFilters.FILTER_SPELL_A, SetTargetPointer.PLAYER
|
||||
).setTriggerPhrase("Whenever {this} becomes the target of a spell, "));
|
||||
), StaticFilters.FILTER_SPELL_A, SetTargetPointer.PLAYER, false)
|
||||
.withRuleTextReplacement(false));
|
||||
|
||||
// Stomp
|
||||
// Damage can’t be prevented this turn. Stomp deals 2 damage to any target.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package mage.cards.b;
|
|||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SourceBecomesTargetTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CardsInControllerGraveyardCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
|
@ -35,7 +35,7 @@ public final class BoneshardSlasher extends CardImpl {
|
|||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
||||
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), new CardsInControllerGraveyardCondition(7),
|
||||
"As long as seven or more cards are in your graveyard, {this} gets +2/+2"));
|
||||
Effect effect = new ConditionalContinuousEffect(new GainAbilitySourceEffect(new SourceBecomesTargetTriggeredAbility(new SacrificeSourceEffect())),
|
||||
Effect effect = new ConditionalContinuousEffect(new GainAbilitySourceEffect(new BecomesTargetSourceTriggeredAbility(new SacrificeSourceEffect())),
|
||||
new CardsInControllerGraveyardCondition(7), "and has \"When {this} becomes the target of a spell or ability, sacrifice it.\"");
|
||||
ability.addEffect(effect);
|
||||
ability.setAbilityWord(AbilityWord.THRESHOLD);
|
||||
|
|
|
|||
|
|
@ -105,11 +105,6 @@ class BoseijuWhoSheltersAllCantCounterEffect extends ContinuousRuleModifyingEffe
|
|||
return new BoseijuWhoSheltersAllCantCounterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject sourceObject = game.getObject(source);
|
||||
|
|
|
|||
|
|
@ -119,11 +119,6 @@ class DeterminedEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new DeterminedEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject sourceObject = game.getObject(source);
|
||||
|
|
|
|||
|
|
@ -66,11 +66,6 @@ class BrandOfIllOmenEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrandOfIllOmenEffect copy() {
|
||||
return new BrandOfIllOmenEffect(this);
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ class BrenardGingerSculptorEffect extends OneShotEffect {
|
|||
);
|
||||
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game) + 1));
|
||||
effect.setBecomesArtifact(true);
|
||||
effect.setAdditionalSubType(SubType.FOOD);
|
||||
effect.setAdditionalSubType(SubType.GOLEM);
|
||||
effect.withAdditionalSubType(SubType.FOOD);
|
||||
effect.withAdditionalSubType(SubType.GOLEM);
|
||||
effect.addAdditionalAbilities(new FoodAbility(false));
|
||||
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.keyword.DisturbAbility;
|
||||
import mage.abilities.meta.OrTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.other.AuraSpellPredicate;
|
||||
import mage.game.permanent.token.SpiritWhiteToken;
|
||||
import mage.game.stack.Spell;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -22,6 +22,12 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class BrineComber extends CardImpl {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("an Aura spell");
|
||||
|
||||
static {
|
||||
filter.add(AuraSpellPredicate.instance);
|
||||
}
|
||||
|
||||
public BrineComber(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}");
|
||||
|
||||
|
|
@ -31,7 +37,10 @@ public final class BrineComber extends CardImpl {
|
|||
this.secondSideCardClazz = mage.cards.b.BrineboundGift.class;
|
||||
|
||||
// Whenever Brine Comber enters the battlefield or becomes the target of an Aura spell, create a 1/1 white Spirit creature token with flying.
|
||||
this.addAbility(new BrineComberTriggeredAbility());
|
||||
this.addAbility(new OrTriggeredAbility(Zone.ALL, new CreateTokenEffect(new SpiritWhiteToken()), false,
|
||||
"Whenever {this} enters the battlefield or becomes the target of an Aura spell, ",
|
||||
new EntersBattlefieldTriggeredAbility(null),
|
||||
new BecomesTargetSourceTriggeredAbility(null, filter)));
|
||||
|
||||
// Disturb {W}{U}
|
||||
this.addAbility(new DisturbAbility(this, "{W}{U}"));
|
||||
|
|
@ -46,54 +55,3 @@ public final class BrineComber extends CardImpl {
|
|||
return new BrineComber(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BrineComberTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
BrineComberTriggeredAbility() {
|
||||
super(Zone.ALL, new CreateTokenEffect(new SpiritWhiteToken()));
|
||||
}
|
||||
|
||||
private BrineComberTriggeredAbility(final BrineComberTriggeredAbility effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrineComberTriggeredAbility copy() {
|
||||
return new BrineComberTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
|
||||
|| event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case ENTERS_THE_BATTLEFIELD:
|
||||
return event.getTargetId().equals(getSourceId());
|
||||
case TARGETED:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (this.getSourcePermanentIfItStillExists(game) == null
|
||||
|| !event.getTargetId().equals(getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = game.getSpell(event.getSourceId());
|
||||
if(spell == null) {
|
||||
return false;
|
||||
}
|
||||
SpellAbility spellAbility = (SpellAbility) spell.getStackAbility();
|
||||
return spellAbility != null
|
||||
&& spellAbility.getCharacteristics(game).hasSubtype(SubType.AURA, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} enters the battlefield or becomes the target " +
|
||||
"of an Aura spell, create a 1/1 white Spirit creature token with flying.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BecomesTargetAttachedTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.PutIntoGraveFromAnywhereSourceAbility;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.ExileSourceEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.abilities.meta.OrTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.other.AuraSpellPredicate;
|
||||
import mage.game.permanent.token.SpiritWhiteToken;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
|
@ -28,6 +25,12 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class BrineboundGift extends CardImpl {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("an Aura spell");
|
||||
|
||||
static {
|
||||
filter.add(AuraSpellPredicate.instance);
|
||||
}
|
||||
|
||||
public BrineboundGift(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "");
|
||||
|
||||
|
|
@ -44,7 +47,10 @@ public final class BrineboundGift extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// Whenever Brinebound Gift enters the battlefield or enchanted creature becomes the target of an Aura spell, create a 1/1 white Spirit creature token with flying.
|
||||
this.addAbility(new BrineboundGiftTriggeredAbility());
|
||||
this.addAbility(new OrTriggeredAbility(Zone.ALL, new CreateTokenEffect(new SpiritWhiteToken()), false,
|
||||
"Whenever {this} enters the battlefield or enchanted creature becomes the target of an Aura spell, ",
|
||||
new EntersBattlefieldTriggeredAbility(null),
|
||||
new BecomesTargetAttachedTriggeredAbility(null, filter, SetTargetPointer.NONE, false)));
|
||||
|
||||
// If Brinebound Gift would be put into a graveyard from anywhere, exile it instead.
|
||||
this.addAbility(new PutIntoGraveFromAnywhereSourceAbility(new ExileSourceEffect().setText("exile it instead")));
|
||||
|
|
@ -59,49 +65,3 @@ public final class BrineboundGift extends CardImpl {
|
|||
return new BrineboundGift(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BrineboundGiftTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
BrineboundGiftTriggeredAbility() {
|
||||
super(Zone.ALL, new CreateTokenEffect(new SpiritWhiteToken()));
|
||||
}
|
||||
|
||||
private BrineboundGiftTriggeredAbility(final BrineboundGiftTriggeredAbility effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrineboundGiftTriggeredAbility copy() {
|
||||
return new BrineboundGiftTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
|
||||
|| event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case ENTERS_THE_BATTLEFIELD:
|
||||
return event.getTargetId().equals(getSourceId());
|
||||
case TARGETED:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = this.getSourcePermanentOrLKI(game);
|
||||
if (permanent == null || !event.getTargetId().equals(permanent.getAttachedTo())) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = game.getSpell(event.getSourceId());
|
||||
return spell != null && spell.hasSubtype(SubType.AURA, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} enters the battlefield or enchanted creature becomes the target " +
|
||||
"of an Aura spell, create a 1/1 white Spirit creature token with flying.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,6 @@ class BriselaVoiceOfNightmaresCantCastEffect extends ContinuousRuleModifyingEffe
|
|||
return new BriselaVoiceOfNightmaresCantCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject mageObject = game.getObject(source);
|
||||
|
|
|
|||
85
Mage.Sets/src/mage/cards/c/CallForthTheTempest.java
Normal file
85
Mage.Sets/src/mage/cards/c/CallForthTheTempest.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageAllEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.CascadeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class CallForthTheTempest extends CardImpl {
|
||||
|
||||
private static Hint hint = new ValueHint("Total mana value of other spells you've cast this turn", CallForthTheTempestDynamicValue.instance);
|
||||
|
||||
public CallForthTheTempest(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{R}{R}{R}");
|
||||
|
||||
// Cascade
|
||||
this.addAbility(new CascadeAbility(false).setRuleAtTheTop(true));
|
||||
|
||||
// Cascade
|
||||
this.addAbility(new CascadeAbility(false).setRuleAtTheTop(true));
|
||||
|
||||
// Call Forth the Tempest deals damage to each creature your opponents control equal to the total mana value of other spells you've cast this turn.
|
||||
this.getSpellAbility().addEffect(new DamageAllEffect(
|
||||
CallForthTheTempestDynamicValue.instance,
|
||||
StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE
|
||||
));
|
||||
this.getSpellAbility().addHint(hint);
|
||||
}
|
||||
|
||||
private CallForthTheTempest(final CallForthTheTempest card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallForthTheTempest copy() {
|
||||
return new CallForthTheTempest(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum CallForthTheTempestDynamicValue implements DynamicValue {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
if (watcher == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return watcher
|
||||
.getSpellsCastThisTurn(sourceAbility.getControllerId())
|
||||
.stream()
|
||||
.filter(s -> s != null && !s.getSourceId().equals(sourceAbility.getSourceId()))
|
||||
.mapToInt(s -> s.getManaValue())
|
||||
.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallForthTheTempestDynamicValue copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "total mana value of other spells you've cast this turn";
|
||||
}
|
||||
}
|
||||
|
|
@ -25,8 +25,8 @@ import mage.target.common.TargetCardInLibrary;
|
|||
*/
|
||||
public final class CaptainPhasma extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Nontoken trooper creatures");
|
||||
private static final FilterCreatureCard filterCard = new FilterCreatureCard("Trooper card");
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken Trooper creatures");
|
||||
private static final FilterCreatureCard filterCard = new FilterCreatureCard("Trooper creature card");
|
||||
|
||||
static {
|
||||
filter.add(SubType.TROOPER.getPredicate());
|
||||
|
|
@ -44,11 +44,9 @@ public final class CaptainPhasma extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Nontoken Trooper creatures you control have "When this creature enters the battlefield, create 1/1/ white Trooper creature token."
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TrooperToken())
|
||||
.setText("When this creature enters the battlefield, create a 1/1 white Trooper creature token"),
|
||||
false, true);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new GainAbilityControlledEffect(ability, Duration.WhileOnBattlefield, filter, false)));
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TrooperToken()), false)
|
||||
.setTriggerPhrase("When this creature enters the battlefield, ");
|
||||
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(ability, Duration.WhileOnBattlefield, filter, false)));
|
||||
|
||||
// {W}{U}{B}{R}{G}: Search your library for a Trooper creature card, reveal it, put it into your hand, then shuffle your library.
|
||||
this.addAbility(new SimpleActivatedAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true), new ManaCostsImpl<>("{W}{U}{B}{R}{G}")));
|
||||
|
|
|
|||
|
|
@ -177,11 +177,6 @@ class CavernOfSoulsCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new CavernOfSoulsCantCounterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
MageObject sourceObject = game.getObject(source);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SourceBecomesTargetTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.effects.common.MillCardsControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -22,7 +22,7 @@ public final class CephalidAristocrat extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// Whenever Cephalid Aristocrat becomes the target of a spell or ability, put the top two cards of your library into your graveyard.
|
||||
this.addAbility(new SourceBecomesTargetTriggeredAbility(new MillCardsControllerEffect(2)));
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(new MillCardsControllerEffect(2)));
|
||||
}
|
||||
|
||||
private CephalidAristocrat(final CephalidAristocrat card) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package mage.cards.c;
|
|||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SourceBecomesTargetTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
|
@ -35,7 +35,7 @@ public final class CephalidIllusionist extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Whenever Cephalid Illusionist becomes the target of a spell or ability, put the top three cards of your library into your graveyard.
|
||||
this.addAbility(new SourceBecomesTargetTriggeredAbility(new MillCardsControllerEffect(3)));
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(new MillCardsControllerEffect(3)));
|
||||
|
||||
// {2}{U}, {tap}: Prevent all combat damage that would be dealt to
|
||||
Effect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, true);
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ class ChromeMoxManaEffect extends ManaEffect {
|
|||
if (choice.getChoices().size() == 1) {
|
||||
choice.setChoice(choice.getChoices().iterator().next());
|
||||
} else {
|
||||
if (!player.choose(outcome, choice, game)) {
|
||||
if (!player.choose(Outcome.PutManaInPool, choice, game)) {
|
||||
return mana;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.MageInt;
|
|||
import mage.Mana;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.mana.DynamicManaAbility;
|
||||
import mage.constants.SubType;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -29,7 +30,7 @@ public final class CircleOfDreamsDruid extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// {T}: Add {G} for each creature you control.
|
||||
this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), xValue));
|
||||
this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), xValue).addHint(new ValueHint("Creatures you control", xValue)));
|
||||
}
|
||||
|
||||
private CircleOfDreamsDruid(final CircleOfDreamsDruid card) {
|
||||
|
|
|
|||
|
|
@ -120,10 +120,14 @@ class CircuDimirLobotomistRuleModifyingEffect extends ContinuousRuleModifyingEff
|
|||
return "You can't cast this spell because a card with the same name is exiled by " + CardUtil.getSourceName(game, source) + '.';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.CAST_SPELL
|
||||
|| !game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
|
||||
if (!game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import mage.constants.Zone;
|
|||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.predicate.permanent.TokenPredicate;
|
||||
import mage.game.Game;
|
||||
|
|
@ -22,16 +23,24 @@ import mage.game.events.GameEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static mage.cards.c.CityInABottle.getArabianNightsNamePredicates;
|
||||
|
||||
/**
|
||||
* @author emerald000
|
||||
*/
|
||||
public final class CityInABottle extends CardImpl {
|
||||
|
||||
// Arabian Nights names per CR 206.3a
|
||||
static final List<NamePredicate> ARABIAN_NIGHTS_CARD_NAME_PREDICATES = new ArrayList<>();
|
||||
static {
|
||||
List<String> nameStrings = Arrays.asList("Abu Ja'far", "Aladdin", "Aladdin's Lamp", "Aladdin's Ring", "Ali Baba", "Ali from Cairo", "Army of Allah", "Bazaar of Baghdad", "Bird Maiden", "Bottle of Suleiman", "Brass Man", "Camel", "City in a Bottle", "City of Brass", "Cuombajj Witches", "Cyclone", "Dancing Scimitar", "Dandan", "Desert", "Desert Nomads", "Desert Twister", "Diamond Valley", "Drop of Honey", "Ebony Horse", "Elephant Graveyard", "El-Hajjaj", "Erg Raiders", "Erhnam Djinn", "Eye for an Eye", "Fishliver Oil", "Flying Carpet", "Flying Men", "Ghazban Ogre", "Giant Tortoise", "Guardian Beast", "Hasran Ogress", "Hurr Jackal", "Ifh-Biff Efreet", "Island Fish Jasconius", "Island of Wak-Wak", "Jandor's Ring", "Jandor's Saddlebags", "Jeweled Bird", "Jihad", "Junun Efreet", "Juzam Djinn", "Khabal Ghoul", "King Suleiman", "Kird Ape", "Library of Alexandria", "Magnetic Mountain", "Merchant Ship", "Metamorphosis", "Mijae Djinn", "Moorish Cavalry", "Nafs Asp", "Oasis", "Old Man of the Sea", "Oubliette", "Piety", "Pyramids", "Repentant Blacksmith", "Ring of Ma'ruf", "Rukh Egg", "Sandals of Abdallah", "Sandstorm", "Serendib Djinn", "Serendib Efreet", "Shahrazad", "Sindbad", "Singing Tree", "Sorceress Queen", "Stone-Throwing Devils", "Unstable Mutation", "War Elephant", "Wyluli Wolf", "Ydwen Efreet");
|
||||
for (String name : nameStrings) {
|
||||
ARABIAN_NIGHTS_CARD_NAME_PREDICATES.add(new NamePredicate(name));
|
||||
}
|
||||
}
|
||||
|
||||
public CityInABottle(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
|
|
@ -39,7 +48,7 @@ public final class CityInABottle extends CardImpl {
|
|||
this.addAbility(new CityInABottleStateTriggeredAbility());
|
||||
|
||||
// Players can't play cards originally printed in the Arabian Nights expansion.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CityInABottleCantPlayEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(new CityInABottleCantPlayEffect()));
|
||||
}
|
||||
|
||||
private CityInABottle(final CityInABottle card) {
|
||||
|
|
@ -51,100 +60,20 @@ public final class CityInABottle extends CardImpl {
|
|||
return new CityInABottle(this);
|
||||
}
|
||||
|
||||
static public List<NamePredicate> getArabianNightsNamePredicates() {
|
||||
List<NamePredicate> namePredicatesArabianNights = new ArrayList<>();
|
||||
namePredicatesArabianNights.add(new NamePredicate("Abu Ja'far"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Aladdin"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Aladdin's Lamp"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Aladdin's Ring"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ali Baba"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ali from Cairo"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Army of Allah"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Bazaar of Baghdad"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Bird Maiden"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Bottle of Suleiman"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Brass Man"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Camel"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("City of Brass"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Cuombajj Witches"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Cyclone"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Dancing Scimitar"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Dandan"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Desert"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Desert Nomads"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Desert Twister"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Diamond Valley"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Drop of Honey"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ebony Horse"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("El-Hajjaj"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Elephant Graveyard"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Erg Raiders"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Erhnam Djinn"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Eye for an Eye"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Fishliver Oil"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Flying Carpet"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Flying Men"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ghazban Ogre"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Giant Tortoise"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Guardian Beast"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Hasran Ogress"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Hurr Jackal"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ifh-Biff Efreet"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Island Fish Jasconius"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Island of Wak-Wak"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Jandor's Ring"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Jandor's Saddlebags"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Jeweled Bird"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Jihad"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Junun Efreet"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Juzam Djinn"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Khabal Ghoul"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("King Suleiman"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Kird Ape"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Library of Alexandria"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Magnetic Mountain"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Merchant Ship"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Metamorphosis"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Mijae Djinn"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Moorish Cavalry"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Nafs Asp"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Oasis"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Old Man of the Sea"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Oubliette"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Piety"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Pyramids"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Repentant Blacksmith"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ring of Ma'ruf"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Rukh Egg"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Sandals of Abdallah"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Sandstorm"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Serendib Djinn"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Serendib Efreet"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Shahrazad"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Sindbad"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Singing Tree"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Sorceress Queen"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Stone-Throwing Devils"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Unstable Mutation"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("War Elephant"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Wyluli Wolf"));
|
||||
namePredicatesArabianNights.add(new NamePredicate("Ydwen Efreet"));
|
||||
return namePredicatesArabianNights;
|
||||
}
|
||||
}
|
||||
|
||||
class CityInABottleStateTriggeredAbility extends StateTriggeredAbility {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("a nontoken permanent originally printed in the Arabian Nights expansion other than City in a Bottle");
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("other nontoken permanents with a name originally printed in the Arabian Nights expansion");
|
||||
static {
|
||||
filter.add(TokenPredicate.FALSE);
|
||||
filter.add(Predicates.or(getArabianNightsNamePredicates()));
|
||||
|
||||
filter.add(Predicates.or(CityInABottle.ARABIAN_NIGHTS_CARD_NAME_PREDICATES));
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
CityInABottleStateTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new CityInABottleSacrificeEffect());
|
||||
setTriggerPhrase("Whenever one or more other nontoken permanents with a name originally printed in the <i>Arabian Nights</i> expansion are on the battlefield, ");
|
||||
}
|
||||
|
||||
private CityInABottleStateTriggeredAbility(final CityInABottleStateTriggeredAbility ability) {
|
||||
|
|
@ -161,24 +90,21 @@ class CityInABottleStateTriggeredAbility extends StateTriggeredAbility {
|
|||
return game.getBattlefield().contains(filter, this.getControllerId(), this, game, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever one or more other nontoken permanents with a name originally printed in the <i>Arabian Nights</i> expansion are on the battlefield, their controllers sacrifice them";
|
||||
}
|
||||
}
|
||||
|
||||
class CityInABottleSacrificeEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("a nontoken permanent originally printed in the Arabian Nights expansion other than City in a Bottle");
|
||||
private static final FilterPermanent filter = new FilterPermanent("other nontoken permanents with a name originally printed in the Arabian Nights expansion");
|
||||
|
||||
static {
|
||||
filter.add(TokenPredicate.FALSE);
|
||||
filter.add(Predicates.or(getArabianNightsNamePredicates()));
|
||||
filter.add(Predicates.or(CityInABottle.ARABIAN_NIGHTS_CARD_NAME_PREDICATES));
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
CityInABottleSacrificeEffect() {
|
||||
super(Outcome.Sacrifice);
|
||||
this.staticText = "its controller sacrifices it";
|
||||
this.staticText = "their controllers sacrifice them";
|
||||
}
|
||||
|
||||
private CityInABottleSacrificeEffect(final CityInABottleSacrificeEffect effect) {
|
||||
|
|
@ -201,26 +127,21 @@ class CityInABottleSacrificeEffect extends OneShotEffect {
|
|||
|
||||
class CityInABottleCantPlayEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("cards originally printed in the Arabian Nights expansion");
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(getArabianNightsNamePredicates()));
|
||||
filter.add(Predicates.or(CityInABottle.ARABIAN_NIGHTS_CARD_NAME_PREDICATES));
|
||||
}
|
||||
|
||||
CityInABottleCantPlayEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
staticText = "Players can't play cards originally printed in the <i>Arabian Nights</i> expansion";
|
||||
staticText = "Players can't cast spells or play lands with a name originally printed in the <i>Arabian Nights</i> expansion";
|
||||
}
|
||||
|
||||
private CityInABottleCantPlayEffect(final CityInABottleCantPlayEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CityInABottleCantPlayEffect copy() {
|
||||
return new CityInABottleCantPlayEffect(this);
|
||||
|
|
@ -228,7 +149,7 @@ class CityInABottleCantPlayEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
return "You can't play cards originally printed in the Arabian Nights expansion";
|
||||
return "You can't play cards with a name originally printed in the Arabian Nights expansion";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,31 +1,35 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BecomesTargetAnyTriggeredAbility;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
* @author xenohedron
|
||||
*/
|
||||
public final class CloudCover extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent("another permanent you control");
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
public CloudCover(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{U}");
|
||||
|
||||
// Whenever another permanent you control becomes the target of a spell or ability an opponent controls, you may return that permanent to its owner's hand.
|
||||
this.addAbility(new CloudCoverAbility());
|
||||
this.addAbility(new BecomesTargetAnyTriggeredAbility(new ReturnToHandTargetEffect().setText("return that permanent to its owner's hand"),
|
||||
filter, StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS, SetTargetPointer.PERMANENT, true));
|
||||
}
|
||||
|
||||
private CloudCover(final CloudCover card) {
|
||||
|
|
@ -37,44 +41,3 @@ public final class CloudCover extends CardImpl {
|
|||
return new CloudCover(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CloudCoverAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public CloudCoverAbility() {
|
||||
super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), true);
|
||||
}
|
||||
|
||||
private CloudCoverAbility(final CloudCoverAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudCoverAbility copy() {
|
||||
return new CloudCoverAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
Player controller = game.getPlayer(this.getControllerId());
|
||||
if (permanent != null
|
||||
&& permanent.isControlledBy(getControllerId())
|
||||
&& !permanent.getId().equals(this.getSourceId())
|
||||
&& controller != null
|
||||
&& controller.hasOpponent(event.getPlayerId(), game)) {
|
||||
getEffects().get(0).setTargetPointer(new FixedTarget(permanent, game));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever another permanent you control becomes the target of a spell or ability an opponent controls, you may return that permanent to its owner's hand.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,8 +71,9 @@ class CloudsteelKirinEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.WINS
|
||||
|| event.getType() == GameEvent.EventType.LOSES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -53,25 +53,23 @@ class ConjurersBanEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConjurersBanEffect copy() {
|
||||
return new ConjurersBanEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL
|
||||
|| event.getType() == GameEvent.EventType.PLAY_LAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.CAST_SPELL || event.getType() == GameEvent.EventType.PLAY_LAND) {
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
|
||||
return CardUtil.haveSameNames(object, cardName, game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, GameEvent event, Game game) {
|
||||
|
|
|
|||
|
|
@ -101,11 +101,6 @@ class ConquerorsFlailEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
return new ConquerorsFlailEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
|
|
|
|||
|
|
@ -110,11 +110,6 @@ class CorneredMarketReplacementEffect extends ContinuousRuleModifyingEffectImpl
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CorneredMarketReplacementEffect copy() {
|
||||
return new CorneredMarketReplacementEffect(this);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import mage.choices.Choice;
|
|||
import mage.choices.ChoiceColor;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
|
@ -148,7 +149,7 @@ class CorruptedGrafstoneManaEffect extends ManaEffect {
|
|||
if (choice.getChoices().size() == 1) {
|
||||
choice.setChoice(choice.getChoices().iterator().next());
|
||||
} else {
|
||||
if (!player.choose(outcome, choice, game)) {
|
||||
if (!player.choose(Outcome.PutManaInPool, choice, game)) {
|
||||
return mana;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,11 +64,6 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec
|
|||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CouncilOfTheAbsoluteReplacementEffect copy() {
|
||||
return new CouncilOfTheAbsoluteReplacementEffect(this);
|
||||
|
|
|
|||
|
|
@ -1,21 +1,16 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BecomesTargetAnyTriggeredAbility;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dustinconrad
|
||||
* @author xenohedron
|
||||
*/
|
||||
public final class Cowardice extends CardImpl {
|
||||
|
||||
|
|
@ -23,7 +18,7 @@ public final class Cowardice extends CardImpl {
|
|||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}{U}");
|
||||
|
||||
// Whenever a creature becomes the target of a spell or ability, return that creature to its owner's hand.
|
||||
this.addAbility(new CowardiceTriggeredAbility());
|
||||
this.addAbility(new BecomesTargetAnyTriggeredAbility(new ReturnToHandTargetEffect(), StaticFilters.FILTER_PERMANENT_A_CREATURE));
|
||||
}
|
||||
|
||||
private Cowardice(final Cowardice card) {
|
||||
|
|
@ -35,39 +30,3 @@ public final class Cowardice extends CardImpl {
|
|||
return new Cowardice(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CowardiceTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public CowardiceTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), false);
|
||||
}
|
||||
|
||||
private CowardiceTriggeredAbility(final CowardiceTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && permanent.isCreature(game)) {
|
||||
getEffects().get(0).setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a creature becomes the target of a spell or ability, return that creature to its owner's hand.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CowardiceTriggeredAbility copy() {
|
||||
return new CowardiceTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
|
|
@ -57,12 +56,7 @@ enum CreatureBondValue implements DynamicValue {
|
|||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
// In the case that the enchantment is blinked
|
||||
Permanent enchantment = (Permanent) game.getLastKnownInformation(sourceAbility.getSourceId(), Zone.BATTLEFIELD);
|
||||
if (enchantment == null) {
|
||||
// It was not blinked, use the standard method
|
||||
enchantment = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId());
|
||||
}
|
||||
Permanent enchantment = sourceAbility.getSourcePermanentOrLKI(game);
|
||||
if (enchantment == null) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package mage.cards.c;
|
|||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SourceBecomesTargetTriggeredAbility;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||
|
|
@ -36,13 +36,13 @@ public final class CrystallineNautilus extends CardImpl {
|
|||
this.addAbility(new BestowAbility(this, "{3}{U}{U}"));
|
||||
|
||||
// When Crystalline Nautilus becomes the target of a spell or ability, sacrifice it.
|
||||
this.addAbility(new SourceBecomesTargetTriggeredAbility(new SacrificeSourceEffect()));
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(new SacrificeSourceEffect()));
|
||||
|
||||
// Enchanted creature gets +4/+4 and has "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
Effect effect = new BoostEnchantedEffect(4,4,Duration.WhileOnBattlefield);
|
||||
effect.setText("Enchanted creature gets +4/+4");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
effect = new GainAbilityAttachedEffect(new SourceBecomesTargetTriggeredAbility(new SacrificeSourceEffect()), AttachmentType.AURA, Duration.WhileOnBattlefield);
|
||||
effect = new GainAbilityAttachedEffect(new BecomesTargetSourceTriggeredAbility(new SacrificeSourceEffect()), AttachmentType.AURA, Duration.WhileOnBattlefield);
|
||||
effect.setText("and has \"When this creature becomes the target of a spell or ability, sacrifice it.\"");
|
||||
ability.addEffect(effect);
|
||||
this.addAbility(ability);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import mage.target.targetpointer.FixedTarget;
|
|||
import java.util.UUID;
|
||||
import mage.abilities.common.EnchantedPlayerAttackedTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.players.Player;
|
||||
|
||||
|
|
@ -71,12 +70,7 @@ class CurseOfBountyEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// In the case that the enchantment is blinked
|
||||
Permanent enchantment = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
if (enchantment == null) {
|
||||
// It was not blinked, use the standard method
|
||||
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
}
|
||||
Permanent enchantment = source.getSourcePermanentOrLKI(game);
|
||||
if (enchantment != null) {
|
||||
Player enchantedPlayer = game.getPlayer(enchantment.getAttachedTo());
|
||||
if (enchantedPlayer != null) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.ZombieToken;
|
||||
|
|
@ -72,12 +71,7 @@ class CurseOfDisturbanceEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// In the case that the enchantment is blinked
|
||||
Permanent enchantment = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
if (enchantment == null) {
|
||||
// It was not blinked, use the standard method
|
||||
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
}
|
||||
Permanent enchantment = source.getSourcePermanentOrLKI(game);
|
||||
if (enchantment != null) {
|
||||
Player enchantedPlayer = game.getPlayer(enchantment.getAttachedTo());
|
||||
if (enchantedPlayer != null) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import mage.watchers.common.CastSpellLastTurnWatcher;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public final class CurseOfExhaustion extends CardImpl {
|
||||
|
|
@ -66,22 +65,18 @@ class CurseOfExhaustionEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.CAST_SPELL) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if (enchantment != null && enchantment.getAttachedTo() != null) {
|
||||
Player player = game.getPlayer(enchantment.getAttachedTo());
|
||||
if (player != null && event.getPlayerId().equals(player.getId())) {
|
||||
CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) > 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import mage.target.targetpointer.FixedTarget;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
* @author Saga
|
||||
|
|
@ -72,12 +71,7 @@ class CurseOfOpulenceEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// In the case that the enchantment is blinked
|
||||
Permanent enchantment = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
if (enchantment == null) {
|
||||
// It was not blinked, use the standard method
|
||||
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
}
|
||||
Permanent enchantment = source.getSourcePermanentOrLKI(game);
|
||||
if (enchantment == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
|
@ -70,12 +69,7 @@ class CurseOfVerbosityEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// In the case that the enchantment is blinked
|
||||
Permanent enchantment = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
if (enchantment == null) {
|
||||
// It was not blinked, use the standard method
|
||||
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
}
|
||||
Permanent enchantment = source.getSourcePermanentOrLKI(game);
|
||||
if (enchantment != null) {
|
||||
Player enchantedPlayer = game.getPlayer(enchantment.getAttachedTo());
|
||||
if (enchantedPlayer != null) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EnchantedPlayerAttackedTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.GainLifeTargetEffect;
|
||||
import mage.constants.Zone;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
|
|
@ -70,12 +69,7 @@ class CurseOfVitalityEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
// In the case that the enchantment is blinked
|
||||
Permanent enchantment = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
if (enchantment == null) {
|
||||
// It was not blinked, use the standard method
|
||||
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
}
|
||||
Permanent enchantment = source.getSourcePermanentOrLKI(game);
|
||||
if (enchantment != null) {
|
||||
Player enchantedPlayer = game.getPlayer(enchantment.getAttachedTo());
|
||||
if (enchantedPlayer != null) {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue