mirror of
https://github.com/magefree/mage.git
synced 2026-01-19 01:39:58 -08:00
Merge branch 'master' into refactor/multiple-names
This commit is contained in:
commit
f4c55dfc45
67 changed files with 1228 additions and 169 deletions
|
|
@ -445,7 +445,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
return;
|
||||
}
|
||||
cardInfoPane.setLocation(40, 40);
|
||||
cardInfoPane.setBackground(new Color(0, 0, 0, 255)); // use non-transparent background to full draw, see bug example in #12261
|
||||
UI.addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane);
|
||||
|
||||
MageRoundPane popupContainer = new MageRoundPane();
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@
|
|||
panelCardArea.setOpaque(false);
|
||||
cardArea.setOpaque(false);
|
||||
panelCardArea.getViewport().setOpaque(false);
|
||||
panelControl.setBackground(new Color(250, 250, 250, 150));
|
||||
panelControl.setBackground(PreferencesDialog.getCurrentTheme().getDeckEditorToolbarBackgroundColor());
|
||||
panelControl.setOpaque(true);
|
||||
cbSortBy.setModel(new DefaultComboBoxModel<>(SortBy.values()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -857,7 +857,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
|
|||
|
||||
JPanel toolbar = new JPanel(new BorderLayout());
|
||||
JPanel toolbarInner = new JPanel();
|
||||
toolbar.setBackground(new Color(250, 250, 250, 150));
|
||||
toolbar.setBackground(PreferencesDialog.getCurrentTheme().getDeckEditorToolbarBackgroundColor());
|
||||
toolbar.setOpaque(true);
|
||||
toolbarInner.setOpaque(false);
|
||||
toolbarInner.add(deckNameAndCountLabel);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import mage.cards.repository.*;
|
|||
import mage.client.MageFrame;
|
||||
import mage.client.cards.*;
|
||||
import mage.client.constants.Constants.SortBy;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.deckeditor.table.TableModel;
|
||||
import mage.client.dialog.CheckBoxList;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
|
|
@ -97,11 +98,11 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
jTextFieldSearch.addActionListener(searchAction);
|
||||
|
||||
// make the components more readable
|
||||
tbColor.setBackground(new Color(250, 250, 250, 150));
|
||||
tbColor.setBackground(PreferencesDialog.getCurrentTheme().getDeckEditorToolbarBackgroundColor());
|
||||
tbColor.setOpaque(true); // false = transparent
|
||||
tbTypes.setBackground(new Color(250, 250, 250, 150));
|
||||
tbTypes.setBackground(PreferencesDialog.getCurrentTheme().getDeckEditorToolbarBackgroundColor());
|
||||
tbTypes.setOpaque(true); // false = transparent
|
||||
cardSelectorBottomPanel.setBackground(new Color(250, 250, 250, 150));
|
||||
cardSelectorBottomPanel.setBackground(PreferencesDialog.getCurrentTheme().getDeckEditorToolbarBackgroundColor());
|
||||
cardSelectorBottomPanel.setOpaque(true); // false = transparent
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ public class PickChoiceDialog extends MageDialog {
|
|||
// as card name
|
||||
cardInfo.init(item.getHint(), this.bigCard, this.gameId);
|
||||
} else if (item.getHintType() == ChoiceHintType.CARD_DUNGEON) {
|
||||
// as card name
|
||||
// as dungeon name
|
||||
CardView cardView = new CardView(new DungeonView(Dungeon.createDungeon(item.getHint(), true)));
|
||||
cardInfo.init(cardView, this.bigCard, this.gameId);
|
||||
} else if (item.getHintType() == ChoiceHintType.GAME_OBJECT) {
|
||||
|
|
|
|||
|
|
@ -13,29 +13,29 @@ import java.awt.*;
|
|||
*/
|
||||
public enum ThemeType {
|
||||
// https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html
|
||||
DEFAULT("Default",
|
||||
"",
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
new Color(169, 176, 190), // nimbusBlueGrey
|
||||
new Color(214, 217, 223), // control
|
||||
new Color(255, 255, 255), // nimbusLightBackground
|
||||
new Color(242, 242, 189), // info
|
||||
new Color(51, 98, 140), // nimbusBase
|
||||
null, // mageToolbar
|
||||
DEFAULT("Default", // name
|
||||
"", // path
|
||||
true, // hasBackground
|
||||
false, // hasLoginBackground
|
||||
true, // hasBattleBackground
|
||||
true, // hasSkipButtons
|
||||
true, // hasPhaseIcons
|
||||
true, // hasWinLossImages
|
||||
true, // shortcutsVisibleForSkipButtons
|
||||
new Color(169, 176, 190), // nimbusBlueGrey
|
||||
new Color(214, 217, 223), // control
|
||||
new Color(255, 255, 255), // nimbusLightBackground
|
||||
new Color(242, 242, 189), // info
|
||||
new Color(51, 98, 140), // nimbusBase
|
||||
null, // mageToolbar
|
||||
new Color(200, 200, 180, 200), // playerPanel_inactiveBackgroundColor
|
||||
new Color(200, 255, 200, 200), // playerPanel_activeBackgroundColor
|
||||
new Color(131, 94, 83, 200), // playerPanel_deadBackgroundColor
|
||||
// card icons
|
||||
new Color(169, 176, 190),
|
||||
Color.black,
|
||||
new Color(51, 98, 140),
|
||||
Color.black
|
||||
new Color(131, 94, 83, 200), // playerPanel_deadBackgroundColor
|
||||
new Color(250, 250, 250, 150), // deckEditorToolbarBackgroundColor
|
||||
new Color(169, 176, 190), // cardIconsFillColor
|
||||
Color.black, // cardIconsStrokeColor
|
||||
new Color(51, 98, 140), // cardIconsTextColor
|
||||
Color.black // textColor
|
||||
),
|
||||
GREY("Grey",
|
||||
"grey-theme/",
|
||||
|
|
@ -55,6 +55,7 @@ public enum ThemeType {
|
|||
new Color(172, 172, 172, 200), // playerPanel_inactiveBackgroundColor
|
||||
new Color(180, 234, 180, 200), // playerPanel_activeBackgroundColor
|
||||
new Color(99, 99, 99, 200), // playerPanel_deadBackgroundColor
|
||||
new Color(250, 250, 250, 150), // deckEditorToolbarBackgroundColor
|
||||
// card icons
|
||||
new Color(158, 158, 158),
|
||||
Color.black,
|
||||
|
|
@ -79,6 +80,7 @@ public enum ThemeType {
|
|||
new Color(243, 233, 164), // playerPanel_inactiveBackgroundColor
|
||||
new Color(204, 236, 201), // playerPanel_activeBackgroundColor
|
||||
new Color(106, 0, 255), // playerPanel_deadBackgroundColor
|
||||
new Color(250, 250, 250, 150), // deckEditorToolbarBackgroundColor
|
||||
// card icons
|
||||
new Color(246, 136, 158),
|
||||
Color.black,
|
||||
|
|
@ -103,6 +105,7 @@ public enum ThemeType {
|
|||
new Color(219, 193, 172), // playerPanel_inactiveBackgroundColor
|
||||
new Color(204, 236, 201), // playerPanel_activeBackgroundColor
|
||||
new Color(99, 72, 50, 255), // playerPanel_deadBackgroundColor
|
||||
new Color(250, 250, 250, 150), // deckEditorToolbarBackgroundColor
|
||||
// card icons
|
||||
new Color(219, 193, 172),
|
||||
Color.black,
|
||||
|
|
@ -127,6 +130,7 @@ public enum ThemeType {
|
|||
new Color(172, 195, 219), // playerPanel_inactiveBackgroundColor
|
||||
new Color(204, 236, 201), // playerPanel_activeBackgroundColor
|
||||
new Color(50, 68, 99, 255), // playerPanel_deadBackgroundColor
|
||||
new Color(250, 250, 250, 150), // deckEditorToolbarBackgroundColor
|
||||
// card icons
|
||||
new Color(172, 197, 219),
|
||||
Color.black,
|
||||
|
|
@ -142,19 +146,20 @@ public enum ThemeType {
|
|||
true,
|
||||
true,
|
||||
true,
|
||||
new Color(43, 45, 49), // buttons, scrollar background, disabled inputs
|
||||
new Color(49, 51, 56), // window background
|
||||
new Color(58, 56, 64), // inputs, table rows
|
||||
new Color(58, 56, 64), // tooltips
|
||||
new Color(25, 25, 25), // title bars, scrollbar foreground
|
||||
new Color(43, 45, 49), // mageToolbar
|
||||
new Color(43, 45, 49), // playerPanel_inactiveBackgroundColor
|
||||
new Color(64, 61, 56), // playerPanel_activeBackgroundColor
|
||||
new Color(43, 45, 49), // buttons, scrollar background, disabled inputs
|
||||
new Color(49, 51, 56), // window background
|
||||
new Color(58, 56, 64), // inputs, table rows
|
||||
new Color(58, 56, 64), // tooltips
|
||||
new Color(25, 25, 25), // title bars, scrollbar foreground
|
||||
new Color(43, 45, 49), // mageToolbar
|
||||
new Color(43, 45, 49), // playerPanel_inactiveBackgroundColor
|
||||
new Color(64, 61, 56), // playerPanel_activeBackgroundColor
|
||||
new Color(50, 68, 99, 255), // playerPanel_deadBackgroundColor
|
||||
new Color(172, 197, 219),
|
||||
Color.BLACK,
|
||||
new Color(0, 78, 97),
|
||||
new Color(220, 220, 220)
|
||||
new Color(50, 50, 50, 250), // deckEditorToolbarBackgroundColor
|
||||
new Color(172, 197, 219), // cardIconsFillColor
|
||||
Color.BLACK, // cardIconsStrokeColor
|
||||
new Color(0, 78, 97), // cardIconsTextColor
|
||||
new Color(220, 220, 220) // textColor
|
||||
);
|
||||
|
||||
private final String name;
|
||||
|
|
@ -175,6 +180,7 @@ public enum ThemeType {
|
|||
private final Color playerPanel_inactiveBackgroundColor;
|
||||
private final Color playerPanel_activeBackgroundColor;
|
||||
private final Color playerPanel_deadBackgroundColor;
|
||||
private final Color deckEditorToolbarBackgroundColor;
|
||||
// card icons settings (example: flying icon)
|
||||
private final Color cardIconsFillColor;
|
||||
private final Color cardIconsStrokeColor;
|
||||
|
|
@ -201,6 +207,7 @@ public enum ThemeType {
|
|||
Color playerPanel_inactiveBackgroundColor,
|
||||
Color playerPanel_activeBackgroundColor,
|
||||
Color playerPanel_deadBackgroundColor,
|
||||
Color deckEditorToolbarBackgroundColor,
|
||||
Color cardIconsFillColor,
|
||||
Color cardIconsStrokeColor,
|
||||
Color cardIconsTextColor,
|
||||
|
|
@ -224,6 +231,7 @@ public enum ThemeType {
|
|||
this.playerPanel_activeBackgroundColor = playerPanel_activeBackgroundColor;
|
||||
this.playerPanel_deadBackgroundColor = playerPanel_deadBackgroundColor;
|
||||
this.playerPanel_inactiveBackgroundColor = playerPanel_inactiveBackgroundColor;
|
||||
this.deckEditorToolbarBackgroundColor = deckEditorToolbarBackgroundColor;
|
||||
this.cardIconsFillColor = cardIconsFillColor;
|
||||
this.cardIconsStrokeColor = cardIconsStrokeColor;
|
||||
this.cardIconsTextColor = cardIconsTextColor;
|
||||
|
|
@ -292,6 +300,10 @@ public enum ThemeType {
|
|||
return playerPanel_deadBackgroundColor;
|
||||
}
|
||||
|
||||
public Color getDeckEditorToolbarBackgroundColor() {
|
||||
return deckEditorToolbarBackgroundColor;
|
||||
}
|
||||
|
||||
private String getImagePath(String imageType, String name) {
|
||||
return "/" + imageType + "/" + path + name;
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
|
@ -18,7 +18,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
|||
public static final int MAGE_VERSION_MAJOR = 1;
|
||||
public static final int MAGE_VERSION_MINOR = 4;
|
||||
public static final int MAGE_VERSION_RELEASE = 54;
|
||||
public static final String MAGE_VERSION_RELEASE_INFO = "V2"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
|
||||
public static final String MAGE_VERSION_RELEASE_INFO = "V3"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
|
||||
|
||||
// strict mode
|
||||
// Each update requires a strict version
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public class Commander extends AbstractCommander {
|
|||
banned.add("Braids, Cabal Minion");
|
||||
banned.add("Channel");
|
||||
banned.add("Coalition Victory");
|
||||
banned.add("Dockside Extortionist");
|
||||
banned.add("Emrakul, the Aeons Torn");
|
||||
banned.add("Erayo, Soratami Ascendant");
|
||||
banned.add("Fastbond");
|
||||
|
|
@ -29,17 +30,20 @@ public class Commander extends AbstractCommander {
|
|||
banned.add("Griselbrand");
|
||||
banned.add("Hullbreacher");
|
||||
banned.add("Iona, Shield of Emeria");
|
||||
banned.add("Jeweled Lotus");
|
||||
banned.add("Jihad");
|
||||
banned.add("Karakas");
|
||||
banned.add("Leovold, Emissary of Trest");
|
||||
banned.add("Library of Alexandria");
|
||||
banned.add("Limited Resources");
|
||||
banned.add("Lutri, the Spellchaser");
|
||||
banned.add("Mana Crypt");
|
||||
banned.add("Mox Emerald");
|
||||
banned.add("Mox Jet");
|
||||
banned.add("Mox Pearl");
|
||||
banned.add("Mox Ruby");
|
||||
banned.add("Mox Sapphire");
|
||||
banned.add("Nadu, Winged Wisdom");
|
||||
banned.add("Panoptic Mirror");
|
||||
banned.add("Paradox Engine");
|
||||
banned.add("Primeval Titan");
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public class GameController implements GameCallback {
|
|||
this.tableId = tableId;
|
||||
this.choosingPlayerId = choosingPlayerId;
|
||||
this.gameOptions = gameOptions;
|
||||
this.useResponseIdleTimeout = game.getPlayers().values().stream().anyMatch(Player::isHuman);
|
||||
this.useResponseIdleTimeout = game.getPlayers().values().stream().filter(Player::isHuman).count() > 1;
|
||||
init();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public final class ConductiveMachete extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(2, 1)));
|
||||
|
||||
// Equip {4}
|
||||
this.addAbility(new EquipAbility(4));
|
||||
this.addAbility(new EquipAbility(4, false));
|
||||
}
|
||||
|
||||
private ConductiveMachete(final ConductiveMachete card) {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public final class CursedWindbreaker extends CardImpl {
|
|||
)));
|
||||
|
||||
// Equip {3}
|
||||
this.addAbility(new EquipAbility(3));
|
||||
this.addAbility(new EquipAbility(3, false));
|
||||
}
|
||||
|
||||
private CursedWindbreaker(final CursedWindbreaker card) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public final class DissectionTools extends CardImpl {
|
|||
|
||||
// Equip--Sacrifice a creature.
|
||||
this.addAbility(new EquipAbility(
|
||||
Outcome.BoostCreature, new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_A_CREATURE)
|
||||
Outcome.BoostCreature, new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_A_CREATURE), false
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ import mage.abilities.keyword.HasteAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -29,9 +31,9 @@ public final class EnduringCourage extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// Whenever another creature you control enters, it gets +2/+0 and gains haste until end of turn.
|
||||
Ability ability = new EntersBattlefieldAllTriggeredAbility(
|
||||
Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD,
|
||||
new BoostTargetEffect(2, 0).setText("it gets +2/+0"),
|
||||
StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL
|
||||
StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL, false, SetTargetPointer.PERMANENT
|
||||
);
|
||||
ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance())
|
||||
.setText("and gains haste until end of turn"));
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public final class ExperimentalPilot extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Ward {2}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}"), false));
|
||||
|
||||
// {U}, Discard two cards: Draft a card from Experimental Pilot's spellbook.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public final class JacesSanctum extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
|
||||
|
||||
// Whenever you cast an instant or sorcery spell, scry 1.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(new ScryEffect(1), filter2, false));
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(new ScryEffect(1, false), filter2, false));
|
||||
}
|
||||
|
||||
private JacesSanctum(final JacesSanctum card) {
|
||||
|
|
@ -51,4 +51,4 @@ public final class JacesSanctum extends CardImpl {
|
|||
public JacesSanctum copy() {
|
||||
return new JacesSanctum(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public final class KillersMask extends CardImpl {
|
|||
)));
|
||||
|
||||
// Equip {2}
|
||||
this.addAbility(new EquipAbility(2));
|
||||
this.addAbility(new EquipAbility(2, false));
|
||||
}
|
||||
|
||||
private KillersMask(final KillersMask card) {
|
||||
|
|
|
|||
|
|
@ -95,18 +95,19 @@ class LegionsInitiativeExileEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl();
|
||||
UUID exileZone = CardUtil.getExileZoneId(game, source);
|
||||
game.getBattlefield().getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE,
|
||||
source.getControllerId(), source, game
|
||||
).stream().filter(Objects::nonNull).forEach(cards::add);
|
||||
return player.moveCardsToExile(
|
||||
return controller.moveCardsToExile(
|
||||
cards.getCards(game), source, game, true,
|
||||
CardUtil.getExileZoneId(game, source), CardUtil.getSourceName(game, source)
|
||||
exileZone, CardUtil.getSourceName(game, source)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -120,8 +121,8 @@ class LegionsInitiativeReturnFromExileEffect extends OneShotEffect {
|
|||
|
||||
LegionsInitiativeReturnFromExileEffect() {
|
||||
super(Outcome.PutCardInPlay);
|
||||
staticText = "return those cards to the battlefield under their owner's control " +
|
||||
"and those creatures gain haste until end of turn";
|
||||
staticText = "return those cards to the battlefield under their owner's control "
|
||||
+ "and those creatures gain haste until end of turn";
|
||||
}
|
||||
|
||||
private LegionsInitiativeReturnFromExileEffect(final LegionsInitiativeReturnFromExileEffect effect) {
|
||||
|
|
@ -135,13 +136,15 @@ class LegionsInitiativeReturnFromExileEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source, -1));
|
||||
if (player == null || exileZone == null || exileZone.isEmpty()) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
|
||||
if (controller == null
|
||||
|| exileZone == null
|
||||
|| exileZone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(exileZone);
|
||||
player.moveCards(cards, Zone.BATTLEFIELD, source, game);
|
||||
controller.moveCards(cards, Zone.BATTLEFIELD, source, game);
|
||||
List<Permanent> permanents = cards.stream().map(game::getPermanent).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
if (permanents.isEmpty()) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public final class LongRiverLurker extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// Ward {1}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{1}")));
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{1}"), false));
|
||||
|
||||
// Other Frogs you control have ward {1}.
|
||||
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public final class NashiSearcherInTheDark extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility());
|
||||
this.addAbility(new MenaceAbility(false));
|
||||
|
||||
// Whenever Nashi, Searcher in the Dark deals combat damage to a player, you mill that many cards. You may put any number of legendary and/or enchantment cards from among them into your hand. If you put no cards into your hand this way, put a +1/+1 counter on Nashi.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new NashiSearcherInTheDarkEffect()));
|
||||
|
|
|
|||
115
Mage.Sets/src/mage/cards/n/NikoLightOfHope.java
Normal file
115
Mage.Sets/src/mage/cards/n/NikoLightOfHope.java
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.ShardToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.functions.EmptyCopyApplier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Grath
|
||||
*/
|
||||
public final class NikoLightOfHope extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("nonlegendary creature you control");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
|
||||
}
|
||||
|
||||
public NikoLightOfHope(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Niko, Light of Hope enters, create two Shard tokens.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ShardToken(), 2)));
|
||||
|
||||
// {2}, {T}: Exile target nonlegendary creature you control. Shards you control become copies of it until the beginning of the next end step. Return it to the battlefield under its owner's control at the beginning of the next end step.
|
||||
Ability ability = new SimpleActivatedAbility(new NikoLightOfHopeEffect(), new GenericManaCost(2));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private NikoLightOfHope(final NikoLightOfHope card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NikoLightOfHope copy() {
|
||||
return new NikoLightOfHope(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NikoLightOfHopeEffect extends OneShotEffect {
|
||||
|
||||
NikoLightOfHopeEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Exile target nonlegendary creature you control. Shards you control become copies of it until the beginning of the next end step. Return it to the battlefield under its owner's control at the beginning of the next end step.";
|
||||
}
|
||||
|
||||
private NikoLightOfHopeEffect(final NikoLightOfHopeEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NikoLightOfHopeEffect copy() {
|
||||
return new NikoLightOfHopeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null && controller != null) {
|
||||
if (permanent.moveToExile(source.getSourceId(), "Niko, Light of Hope", source, game)) {
|
||||
FilterPermanent filter = new FilterPermanent("shards");
|
||||
filter.add(SubType.SHARD.getPredicate());
|
||||
for (Permanent copyTo : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
|
||||
game.copyPermanent(Duration.UntilTheNextEndStep, permanent, copyTo.getId(), source, new EmptyCopyApplier());
|
||||
}
|
||||
ExileZone exile = game.getExile().getExileZone(source.getSourceId());
|
||||
if (exile != null && !exile.isEmpty()) {
|
||||
Card card = game.getCard(permanent.getId());
|
||||
if (card != null) {
|
||||
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false);
|
||||
effect.setTargetPointer(new FixedTarget(card.getId()));
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ public final class OracleOfTheAlpha extends CardImpl {
|
|||
this.addAbility(new EntersBattlefieldTriggeredAbility(new OracleOfTheAlphaEffect()));
|
||||
|
||||
// Whenever Oracle of the Alpha attacks, scry 1.
|
||||
this.addAbility(new AttacksTriggeredAbility(new ScryEffect(1)));
|
||||
this.addAbility(new AttacksTriggeredAbility(new ScryEffect(1, false)));
|
||||
}
|
||||
|
||||
private OracleOfTheAlpha(final OracleOfTheAlpha card) {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public final class ReaperOfTheWilds extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Whenever another creature dies, scry 1.</i>
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(new ScryEffect(1), false, true));
|
||||
this.addAbility(new DiesCreatureTriggeredAbility(new ScryEffect(1, false), false, true));
|
||||
// {B}: Reaper of the Wilds gains deathtouch until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{B}")));
|
||||
// {1}{G}: Reaper of the Wilds gains hexproof until end of turn.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public final class SawbladeSkinripper extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility());
|
||||
this.addAbility(new MenaceAbility(false));
|
||||
|
||||
// {2}, Sacrifice another creature or enchantment: Put a +1/+1 counter on Sawblade Skinripper.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public final class StrengthTestingHammer extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// Equip {3}
|
||||
this.addAbility(new EquipAbility(3));
|
||||
this.addAbility(new EquipAbility(3, false));
|
||||
}
|
||||
|
||||
private StrengthTestingHammer(final StrengthTestingHammer card) {
|
||||
|
|
@ -100,6 +100,3 @@ class StrengthTestingHammerEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
63
Mage.Sets/src/mage/cards/t/TegwyllsScouring.java
Normal file
63
Mage.Sets/src/mage/cards/t/TegwyllsScouring.java
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.PayMoreToCastAsThoughtItHadFlashAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.common.TapTargetCost;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DestroyAllEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.filter.predicate.permanent.TappedPredicate;
|
||||
import mage.game.permanent.token.FaerieRogueToken;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author karapuzz14
|
||||
*/
|
||||
public final class TegwyllsScouring extends CardImpl {
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control with flying");
|
||||
|
||||
static {
|
||||
filter.add(new AbilityPredicate(FlyingAbility.class));
|
||||
filter.add(TappedPredicate.UNTAPPED);
|
||||
}
|
||||
|
||||
public TegwyllsScouring(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}");
|
||||
|
||||
|
||||
// You may cast Tegwyll's Scouring as though it had flash by tapping three untapped creatures you control with flying in addition to paying its other costs.
|
||||
Cost asThoughCost = new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true)).setText("");
|
||||
CostsImpl<Cost> costs = new CostsImpl<>().setText("tapping three untapped creatures you control with flying");
|
||||
costs.add(asThoughCost);
|
||||
|
||||
Ability ability = new PayMoreToCastAsThoughtItHadFlashAbility(this, costs);
|
||||
ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES));
|
||||
ability.addEffect(new CreateTokenEffect(new FaerieRogueToken(), 3));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Destroy all creatures.
|
||||
this.getSpellAbility().addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES));
|
||||
|
||||
//Create three 1/1 black Faerie Rogue creature tokens with flying.
|
||||
this.getSpellAbility().addEffect(new CreateTokenEffect(new FaerieRogueToken(), 3));
|
||||
}
|
||||
|
||||
private TegwyllsScouring(final TegwyllsScouring card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TegwyllsScouring copy() {
|
||||
return new TegwyllsScouring(this);
|
||||
}
|
||||
}
|
||||
141
Mage.Sets/src/mage/cards/t/TheLordOfPain.java
Normal file
141
Mage.Sets/src/mage/cards/t/TheLordOfPain.java
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.SpellCastAllTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.CantGainLifeAllEffect;
|
||||
import mage.constants.*;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.filter.FilterPlayer;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Grath
|
||||
*/
|
||||
public final class TheLordOfPain extends CardImpl {
|
||||
public TheLordOfPain(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.ASSASSIN);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility(false));
|
||||
|
||||
// Your opponents can't gain life.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
new CantGainLifeAllEffect(Duration.WhileOnBattlefield, TargetController.OPPONENT)
|
||||
));
|
||||
|
||||
// Whenever a player casts their first spell each turn, choose another target player. The Lord of Pain deals damage equal to that spell's mana value to the chosen player.
|
||||
this.addAbility(new TheLordOfPainTriggeredAbility());
|
||||
}
|
||||
|
||||
private TheLordOfPain(final TheLordOfPain card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheLordOfPain copy() {
|
||||
return new TheLordOfPain(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum TheLordOfPainPredicate implements Predicate<StackObject> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(StackObject input, Game game) {
|
||||
return game.getState()
|
||||
.getWatcher(SpellsCastWatcher.class)
|
||||
.getCount(input.getControllerId()) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
class TheLordOfPainTriggeredAbility extends SpellCastAllTriggeredAbility {
|
||||
private static final FilterSpell filter = new FilterSpell("their first spell each turn");
|
||||
|
||||
static {
|
||||
filter.add(TheLordOfPainPredicate.instance);
|
||||
}
|
||||
|
||||
public TheLordOfPainTriggeredAbility() {
|
||||
super(new TheLordOfPainEffect(), filter, false, SetTargetPointer.PLAYER);
|
||||
}
|
||||
|
||||
protected TheLordOfPainTriggeredAbility(final TheLordOfPainTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheLordOfPainTriggeredAbility copy() {
|
||||
return new TheLordOfPainTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (super.checkTrigger(event, game)) {
|
||||
Player controller = game.getPlayer(getControllerId());
|
||||
Spell spell = (Spell)getEffects().get(0).getValue("spellCast");
|
||||
if (controller != null) {
|
||||
FilterPlayer filter2 = new FilterPlayer("another target player");
|
||||
filter2.add(Predicates.not(new MageObjectReferencePredicate(spell.getControllerId(), game)));
|
||||
TargetPlayer target = new TargetPlayer(1, 1, false, filter2);
|
||||
controller.choose(Outcome.Damage, target, this, game);
|
||||
getEffects().setTargetPointer(new FixedTarget(target.getFirstTarget()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class TheLordOfPainEffect extends OneShotEffect {
|
||||
|
||||
TheLordOfPainEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "choose another target player. {this} deals damage equal to that spell's mana value to the chosen player";
|
||||
}
|
||||
|
||||
private TheLordOfPainEffect(final TheLordOfPainEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TheLordOfPainEffect copy() {
|
||||
return new TheLordOfPainEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Spell spell = (Spell)this.getValue("spellCast");
|
||||
if (spell != null) {
|
||||
int cost = spell.getManaValue();
|
||||
Player target = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (target != null) {
|
||||
target.damage(cost, source.getSourceId(), source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; }
|
||||
}
|
||||
|
|
@ -66,11 +66,12 @@ class TheMindskinnerEffect extends PreventionEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
int amount = event.getAmount();
|
||||
preventDamageAction(event, source, game);
|
||||
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.millCards(event.getAmount(), source, game);
|
||||
player.millCards(amount, source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public final class WinterMisanthropicGuide extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Ward {2}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}"), false));
|
||||
|
||||
// At the beginning of your upkeep, each player draws two cards.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class ZenithChroniclerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
Player controller = game.getPlayer(getControllerId());
|
||||
Spell spell = game.getSpell(event.getTargetId());
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
if (controller != null && spell != null && watcher != null) {
|
||||
if (controller != null && spell != null && watcher != null && spell.getColor(game).isMulticolored()) {
|
||||
int multicoloredSpell = 0;
|
||||
for (Spell spellCastThisTurn : watcher.getSpellsCastThisTurn(spell.getControllerId())) {
|
||||
if (spellCastThisTurn.getColor(game).isMulticolored() && ++multicoloredSpell > 1) {
|
||||
|
|
|
|||
86
Mage.Sets/src/mage/cards/z/ZimoneMysteryUnraveler.java
Normal file
86
Mage.Sets/src/mage/cards/z/ZimoneMysteryUnraveler.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package mage.cards.z;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.LandfallAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect;
|
||||
import mage.abilities.effects.keyword.ManifestDreadEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.card.FaceDownPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
import mage.watchers.common.AbilityResolvedWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Grath
|
||||
*/
|
||||
public final class ZimoneMysteryUnraveler extends CardImpl {
|
||||
|
||||
public ZimoneMysteryUnraveler(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Landfall -- Whenever a land you control enters, manifest dread if this is the first time this ability has resolved this turn. Otherwise, you may turn a permanent you control face up.
|
||||
Ability ability = new LandfallAbility(new IfAbilityHasResolvedXTimesEffect(
|
||||
Outcome.Benefit, 1, new ManifestDreadEffect()
|
||||
).setText("manifest dread if this is the first time this ability has resolved this turn."), false);
|
||||
ability.addEffect(new IfAbilityHasResolvedXTimesEffect(Outcome.Benefit, 2, true, new ZimoneMysteryUnravelerEffect()));
|
||||
this.addAbility(ability, new AbilityResolvedWatcher());
|
||||
}
|
||||
|
||||
private ZimoneMysteryUnraveler(final ZimoneMysteryUnraveler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZimoneMysteryUnraveler copy() {
|
||||
return new ZimoneMysteryUnraveler(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ZimoneMysteryUnravelerEffect extends OneShotEffect {
|
||||
|
||||
public ZimoneMysteryUnravelerEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "you may turn a permanent you control face up";
|
||||
}
|
||||
|
||||
protected ZimoneMysteryUnravelerEffect(final ZimoneMysteryUnravelerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZimoneMysteryUnravelerEffect copy() {
|
||||
return new ZimoneMysteryUnravelerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
FilterControlledPermanent filter = new FilterControlledPermanent("a permanent you control");
|
||||
filter.add(FaceDownPredicate.instance);
|
||||
if (controller != null) {
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(0, 1, filter, true);
|
||||
controller.choose(Outcome.BoostCreature, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
return permanent != null && permanent.turnFaceUp(source, game, source.getControllerId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,13 @@ package mage.sets;
|
|||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
import mage.collation.BoosterCollator;
|
||||
import mage.collation.BoosterStructure;
|
||||
import mage.collation.CardRun;
|
||||
import mage.collation.RarityConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
|
|
@ -20,7 +27,7 @@ public class DominariaRemastered extends ExpansionSet {
|
|||
this.hasBoosters = true;
|
||||
this.hasBasicLands = true;
|
||||
this.maxCardNumberInBooster = 261;
|
||||
this.numBoosterCommon = 10; // Frame/art variants not yet implemented for booster generation
|
||||
this.numBoosterCommon = 10;
|
||||
this.numBoosterUncommon = 3;
|
||||
this.numBoosterRare = 1;
|
||||
this.ratioBoosterMythic = 7; // 60 rare, 20 mythic
|
||||
|
|
@ -484,8 +491,75 @@ public class DominariaRemastered extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Zur the Enchanter", 374, Rarity.RARE, mage.cards.z.ZurTheEnchanter.class, NON_FULL_USE_VARIOUS));
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public BoosterCollator createCollator() {
|
||||
// return new DominariaRemasteredCollator();
|
||||
// }
|
||||
@Override
|
||||
public BoosterCollator createCollator() {
|
||||
return new DominariaRemasteredCollator();
|
||||
}
|
||||
}
|
||||
|
||||
// Booster collation info from https://www.lethe.xyz/mtg/collation/dmr.html
|
||||
// 1/4 of packs contain an old frame rare/mythic
|
||||
// 6% of packs contain a borderles C/U and 17% of packs contain a borderless card
|
||||
// using borderless for 1/3 of the printings of R/M with borderless variations works with those numbers
|
||||
class DominariaRemasteredCollator implements BoosterCollator {
|
||||
private final CardRun commonA = new CardRun(true, "56", "29", "226", "89", "150", "134", "45", "19", "98", "167", "114", "43", "23", "104", "173", "128", "52", "1", "97", "168", "143", "57", "17", "87", "160", "141", "55", "15", "83", "184", "125", "66", "30", "102", "156", "146", "63", "35", "94", "176", "130", "58", "21", "76", "174", "124", "38", "3", "106", "182", "117", "65", "29", "109", "173", "118", "53", "24", "107", "158", "112", "56", "9", "89", "150", "134", "43", "15", "98", "167", "141", "45", "1", "104", "180", "128", "52", "23", "87", "168", "143", "57", "17", "97", "160", "114", "63", "19", "76", "184", "125", "66", "21", "102", "156", "146", "55", "30", "94", "176", "124", "58", "35", "83", "174", "130", "38", "3", "106", "182", "112", "65", "9", "109", "158", "118", "53", "24", "107", "180", "117");
|
||||
private final CardRun commonB = new CardRun(true, "226", "152", "140", "41", "22", "228", "257", "88", "178", "131", "61", "18", "256", "232", "81", "172", "137", "20", "254", "85", "74", "163", "72", "16", "245", "90", "152", "145", "33", "46", "222", "259", "183", "99", "123", "233", "61", "140", "253", "18", "169", "103", "131", "41", "22", "257", "228", "88", "178", "51", "11", "113", "256", "232", "81", "172", "137", "74", "254", "85", "163", "20", "145", "72", "16", "245", "90", "152", "46", "33", "123", "233", "259", "99", "183", "113", "51", "11", "222", "253", "103", "169", "131", "41", "22", "228", "257", "88", "178", "140", "61", "18", "254", "232", "81", "172", "137", "46", "20", "256", "85", "163", "16", "72", "245", "90", "169", "145", "74", "33", "233", "253", "99", "183", "123", "51", "11", "222", "113", "259", "103");
|
||||
private final CardRun uncommonA = new CardRun(true, "251", "164", "44", "207", "129", "170", "80", "122", "221", "14", "157", "8", "93", "234", "213", "119", "2", "54", "260", "220", "120", "154", "49", "215", "10", "231", "153", "42", "252", "219", "84", "216", "70", "225", "214", "79", "255", "64", "210", "142", "251", "44", "207", "164", "129", "170", "80", "221", "122", "157", "14", "93", "8", "213", "119", "234", "54", "2", "260", "49", "120", "154", "220", "215", "10", "42", "153", "231", "252", "219", "84", "216", "70", "225", "214", "79", "255", "64", "210", "142", "251", "44", "164", "207", "129", "170", "80", "221", "122", "14", "157", "8", "93", "213", "234", "119", "54", "2", "260", "220", "215", "154", "49", "120", "10", "231", "153", "42", "219", "252", "84", "216", "70", "225", "214", "79", "255", "64", "210", "142");
|
||||
private final CardRun uncommonB = new CardRun(true, "246", "48", "155", "209", "40", "86", "28", "208", "115", "212", "34", "196", "190", "240", "199", "105", "197", "25", "162", "242", "116", "189", "243", "138", "181", "111", "202", "78", "68", "31", "147", "235", "204", "100", "203", "177", "4", "211", "192", "246", "195", "48", "209", "40", "155", "212", "28", "208", "115", "196", "86", "34", "190", "240", "199", "105", "162", "25", "197", "243", "189", "116", "242", "138", "181", "111", "202", "68", "78", "203", "147", "235", "204", "100", "31", "177", "211", "4", "192", "195", "246", "48", "155", "209", "40", "86", "28", "208", "115", "212", "34", "196", "190", "240", "199", "105", "162", "25", "197", "243", "189", "116", "242", "138", "181", "111", "202", "68", "78", "203", "147", "235", "204", "100", "31", "177", "4", "211", "192", "195");
|
||||
private final CardRun uncommonC = new CardRun(false, "425", "432", "419", "446", "429");
|
||||
private final CardRun rare = new CardRun(false, "186", "186", "186", "186", "443", "443", "149", "149", "149", "149", "438", "438", "187", "187", "187", "187", "187", "187", "39", "39", "39", "39", "39", "39", "151", "151", "151", "151", "439", "439", "75", "75", "75", "75", "75", "75", "77", "77", "77", "77", "424", "424", "241", "241", "241", "241", "241", "241", "217", "217", "217", "217", "217", "217", "218", "218", "218", "218", "218", "218", "244", "244", "454", "188", "188", "188", "188", "444", "444", "47", "47", "47", "47", "417", "417", "5", "5", "5", "5", "5", "5", "6", "6", "6", "6", "412", "412", "82", "82", "82", "82", "426", "426", "159", "159", "159", "159", "159", "159", "50", "50", "418", "161", "161", "161", "161", "161", "161", "121", "121", "121", "121", "433", "433", "223", "223", "447", "247", "247", "247", "247", "455", "455", "7", "7", "7", "7", "7", "7", "126", "126", "126", "126", "434", "434", "224", "224", "224", "224", "448", "448", "248", "248", "248", "248", "248", "248", "191", "191", "445", "249", "249", "249", "249", "249", "249", "227", "227", "227", "227", "449", "449", "165", "165", "165", "165", "165", "165", "166", "166", "166", "127", "127", "435", "229", "229", "450", "12", "12", "12", "12", "12", "12", "230", "230", "230", "230", "451", "451", "13", "13", "413", "250", "250", "250", "250", "456", "456", "91", "91", "91", "91", "91", "91", "60", "60", "60", "60", "421", "421", "59", "59", "59", "59", "420", "420", "92", "92", "92", "92", "92", "92", "95", "95", "427", "171", "171", "440", "62", "62", "62", "62", "62", "62", "132", "132", "132", "132", "132", "132", "96", "96", "96", "96", "428", "428", "133", "133", "133", "133", "133", "133", "193", "193", "193", "193", "193", "193", "194", "194", "194", "194", "194", "194", "198", "198", "198", "198", "198", "198", "101", "101", "101", "101", "101", "101", "175", "175", "175", "175", "175", "175", "26", "26", "26", "27", "27", "27", "27", "27", "27", "135", "135", "135", "135", "135", "135", "136", "136", "136", "136", "436", "436", "139", "139", "139", "200", "200", "200", "200", "200", "200", "201", "201", "201", "201", "201", "201", "67", "67", "67", "67", "67", "67", "258", "258", "258", "258", "258", "258", "144", "144", "144", "144", "144", "144", "179", "179", "441", "32", "32", "414", "69", "69", "422", "236", "236", "236", "236", "452", "452", "237", "237", "237", "237", "237", "237", "71", "71", "423", "238", "238", "238", "238", "238", "238", "239", "239", "453", "108", "108", "430", "73", "73", "73", "73", "73", "73", "36", "36", "36", "36", "415", "415", "261", "261", "261", "261", "261", "261", "148", "148", "437", "185", "185", "185", "185", "442", "442", "37", "37", "37", "37", "416", "416", "205", "205", "205", "205", "205", "205", "110", "110", "431", "206", "206", "206", "206", "206", "206");
|
||||
private final CardRun rareOld = new CardRun(false, "354", "354", "335", "335", "355", "355", "280", "280", "336", "336", "298", "298", "299", "299", "393", "393", "375", "375", "376", "376", "394", "356", "356", "282", "282", "262", "262", "263", "263", "304", "304", "339", "339", "284", "341", "341", "321", "321", "378", "395", "395", "264", "264", "324", "324", "379", "379", "396", "396", "359", "397", "397", "381", "381", "343", "343", "344", "325", "383", "265", "265", "384", "384", "266", "398", "398", "305", "305", "289", "289", "288", "288", "306", "306", "308", "347", "290", "290", "327", "327", "309", "309", "328", "328", "361", "361", "362", "362", "366", "366", "310", "310", "348", "348", "272", "273", "273", "329", "329", "330", "330", "331", "368", "368", "369", "369", "293", "293", "400", "400", "332", "332", "350", "276", "294", "389", "389", "390", "390", "296", "391", "391", "392", "314", "297", "297", "278", "278", "401", "401", "334", "353", "353", "279", "279", "373", "373", "315", "374", "374");
|
||||
private final CardRun retro = new CardRun(false, "300", "316", "281", "377", "301", "337", "317", "357", "302", "303", "338", "318", "340", "283", "319", "320", "410", "285", "322", "358", "323", "286", "380", "287", "342", "404", "382", "345", "267", "385", "399", "326", "268", "408", "360", "346", "307", "386", "291", "292", "402", "363", "364", "365", "269", "270", "367", "271", "274", "370", "349", "311", "406", "275", "371", "312", "387", "372", "388", "295", "313", "333", "277", "351", "352");
|
||||
private final CardRun common = new CardRun(false, "38", "1", "112", "41", "150", "152", "76", "113", "3", "43", "114", "45", "46", "222", "245", "81", "156", "117", "158", "118", "83", "160", "85", "51", "163", "52", "123", "124", "87", "125", "53", "55", "88", "89", "9", "90", "56", "226", "228", "167", "11", "168", "57", "128", "169", "130", "58", "232", "131", "15", "16", "94", "17", "61", "18", "233", "63", "19", "172", "65", "20", "97", "98", "99", "253", "173", "21", "22", "254", "23", "134", "174", "24", "176", "137", "256", "257", "66", "140", "141", "29", "178", "102", "143", "30", "145", "180", "259", "103", "104", "146", "106", "107", "72", "33", "182", "35", "183", "184", "74", "109");
|
||||
private final CardRun land = new CardRun(false, "402", "403", "404", "405", "406", "407", "408", "409", "410", "411");
|
||||
|
||||
private final BoosterStructure AAAAAABBB = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA, commonA,
|
||||
commonB, commonB, commonB
|
||||
);
|
||||
private final BoosterStructure AAAAABBBB = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA,
|
||||
commonB, commonB, commonB, commonB
|
||||
);
|
||||
private final BoosterStructure AAA = new BoosterStructure(uncommonA, uncommonA, uncommonA);
|
||||
private final BoosterStructure BBB = new BoosterStructure(uncommonB, uncommonB, uncommonB);
|
||||
private final BoosterStructure AAC = new BoosterStructure(uncommonA, uncommonA, uncommonC);
|
||||
private final BoosterStructure BBC = new BoosterStructure(uncommonB, uncommonB, uncommonC);
|
||||
|
||||
private final BoosterStructure OR = new BoosterStructure(retro,rare);
|
||||
private final BoosterStructure CO = new BoosterStructure(common,rareOld);
|
||||
private final BoosterStructure L1 = new BoosterStructure(land);
|
||||
|
||||
private final RarityConfiguration commonRuns = new RarityConfiguration(
|
||||
AAAAAABBB, AAAAAABBB,
|
||||
AAAAABBBB, AAAAABBBB, AAAAABBBB
|
||||
);
|
||||
|
||||
private final RarityConfiguration uncommonRuns = new RarityConfiguration(
|
||||
AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA,
|
||||
AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA,
|
||||
AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA,
|
||||
AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA, AAA,
|
||||
AAA, AAA, AAA, AAA, AAA, AAA, AAA,
|
||||
BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB,
|
||||
BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB,
|
||||
BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB,
|
||||
BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB, BBB,
|
||||
BBB, BBB, BBB, BBB, BBB, BBB, BBB,
|
||||
AAC, AAC, AAC,
|
||||
BBC, BBC, BBC
|
||||
);
|
||||
|
||||
private final RarityConfiguration rareRuns = new RarityConfiguration(OR,OR,OR,CO);
|
||||
private final RarityConfiguration landRuns = new RarityConfiguration(L1);
|
||||
|
||||
@Override
|
||||
public List<String> makeBooster() {
|
||||
List<String> booster = new ArrayList<>();
|
||||
booster.addAll(commonRuns.getNext().makeRun());
|
||||
booster.addAll(uncommonRuns.getNext().makeRun());
|
||||
booster.addAll(rareRuns.getNext().makeRun());
|
||||
booster.addAll(landRuns.getNext().makeRun());
|
||||
return booster;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ public final class DuskmournHouseOfHorror extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Murky Sewer", 263, Rarity.COMMON, mage.cards.m.MurkySewer.class));
|
||||
cards.add(new SetCardInfo("Nashi, Searcher in the Dark", 223, Rarity.RARE, mage.cards.n.NashiSearcherInTheDark.class));
|
||||
cards.add(new SetCardInfo("Neglected Manor", 264, Rarity.COMMON, mage.cards.n.NeglectedManor.class));
|
||||
cards.add(new SetCardInfo("Niko, Light of Hope", 224, Rarity.MYTHIC, mage.cards.n.NikoLightOfHope.class));
|
||||
cards.add(new SetCardInfo("Norin, Swift Survivalist", 145, Rarity.UNCOMMON, mage.cards.n.NorinSwiftSurvivalist.class));
|
||||
cards.add(new SetCardInfo("Oblivious Bookworm", 225, Rarity.UNCOMMON, mage.cards.o.ObliviousBookworm.class));
|
||||
cards.add(new SetCardInfo("Optimistic Scavenger", 21, Rarity.UNCOMMON, mage.cards.o.OptimisticScavenger.class));
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Command Tower", 96, Rarity.COMMON, mage.cards.c.CommandTower.class));
|
||||
cards.add(new SetCardInfo("Commander's Sphere", 244, Rarity.COMMON, mage.cards.c.CommandersSphere.class));
|
||||
cards.add(new SetCardInfo("Convert to Slime", 37, Rarity.RARE, mage.cards.c.ConvertToSlime.class));
|
||||
cards.add(new SetCardInfo("Counterspell", 114, Rarity.COMMON, mage.cards.c.Counterspell.class));
|
||||
cards.add(new SetCardInfo("Counterspell", 114, Rarity.UNCOMMON, mage.cards.c.Counterspell.class));
|
||||
cards.add(new SetCardInfo("Crawling Sensation", 173, Rarity.UNCOMMON, mage.cards.c.CrawlingSensation.class));
|
||||
cards.add(new SetCardInfo("Crypt Ghast", 368, Rarity.MYTHIC, mage.cards.c.CryptGhast.class));
|
||||
cards.add(new SetCardInfo("Culling Ritual", 85, Rarity.RARE, mage.cards.c.CullingRitual.class));
|
||||
|
|
@ -134,7 +134,7 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Harsh Mentor", 165, Rarity.RARE, mage.cards.h.HarshMentor.class));
|
||||
cards.add(new SetCardInfo("Haywire Mite", 247, Rarity.UNCOMMON, mage.cards.h.HaywireMite.class));
|
||||
cards.add(new SetCardInfo("Hinterland Harbor", 284, Rarity.RARE, mage.cards.h.HinterlandHarbor.class));
|
||||
cards.add(new SetCardInfo("Hornet Queen", 184, Rarity.MYTHIC, mage.cards.h.HornetQueen.class));
|
||||
cards.add(new SetCardInfo("Hornet Queen", 184, Rarity.RARE, mage.cards.h.HornetQueen.class));
|
||||
cards.add(new SetCardInfo("Hydra Omnivore", 185, Rarity.MYTHIC, mage.cards.h.HydraOmnivore.class));
|
||||
cards.add(new SetCardInfo("Infernal Grasp", 143, Rarity.UNCOMMON, mage.cards.i.InfernalGrasp.class));
|
||||
cards.add(new SetCardInfo("Inkshield", 221, Rarity.RARE, mage.cards.i.Inkshield.class));
|
||||
|
|
@ -257,6 +257,7 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Temur War Shaman", 200, Rarity.RARE, mage.cards.t.TemurWarShaman.class));
|
||||
cards.add(new SetCardInfo("Terminus", 70, Rarity.RARE, mage.cards.t.Terminus.class));
|
||||
cards.add(new SetCardInfo("The Eldest Reborn", 139, Rarity.UNCOMMON, mage.cards.t.TheEldestReborn.class));
|
||||
cards.add(new SetCardInfo("The Lord of Pain", 3, Rarity.MYTHIC, mage.cards.t.TheLordOfPain.class));
|
||||
cards.add(new SetCardInfo("Theater of Horrors", 236, Rarity.RARE, mage.cards.t.TheaterOfHorrors.class));
|
||||
cards.add(new SetCardInfo("They Came from the Pipes", 14, Rarity.RARE, mage.cards.t.TheyCameFromThePipes.class));
|
||||
cards.add(new SetCardInfo("Thirst for Meaning", 129, Rarity.COMMON, mage.cards.t.ThirstForMeaning.class));
|
||||
|
|
@ -292,5 +293,6 @@ public final class DuskmournHouseOfHorrorCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Yavimaya Coast", 327, Rarity.RARE, mage.cards.y.YavimayaCoast.class));
|
||||
cards.add(new SetCardInfo("Yavimaya Elder", 208, Rarity.COMMON, mage.cards.y.YavimayaElder.class));
|
||||
cards.add(new SetCardInfo("Yedora, Grave Gardener", 209, Rarity.UNCOMMON, mage.cards.y.YedoraGraveGardener.class));
|
||||
cards.add(new SetCardInfo("Zimone, Mystery Unraveler", 8, Rarity.MYTHIC, mage.cards.z.ZimoneMysteryUnraveler.class));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ package mage.sets;
|
|||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
import mage.collation.BoosterCollator;
|
||||
import mage.collation.BoosterStructure;
|
||||
import mage.collation.CardRun;
|
||||
import mage.collation.RarityConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
|
|
@ -328,4 +335,62 @@ public final class Lorwyn extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Wydwen, the Biting Gale", 253, Rarity.RARE, mage.cards.w.WydwenTheBitingGale.class));
|
||||
cards.add(new SetCardInfo("Zephyr Net", 98, Rarity.COMMON, mage.cards.z.ZephyrNet.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoosterCollator createCollator() {
|
||||
return new LorwynCollator();
|
||||
}
|
||||
}
|
||||
|
||||
// Booster collation info from https://www.lethe.xyz/mtg/collation/lrw.html
|
||||
// order not known for uncommon runs, but card division is
|
||||
// pack distribution for uncommons not specified, assuming AAB ABB as in Onslaught
|
||||
class LorwynCollator implements BoosterCollator {
|
||||
private final CardRun commonA = new CardRun(true, "91", "191", "128", "197", "177", "35", "77", "108", "260", "231", "32", "84", "189", "214", "126", "23", "181", "134", "77", "231", "258", "156", "33", "189", "90", "128", "211", "126", "35", "96", "227", "148", "48", "91", "161", "103", "229", "260", "181", "32", "78", "227", "156", "143", "23", "96", "103", "148", "211", "258", "20", "84", "191", "108", "197", "33", "78", "177", "134", "229", "161", "48", "90", "143", "214", "20");
|
||||
private final CardRun commonB = new CardRun(true, "118", "57", "17", "212", "110", "190", "68", "201", "34", "265", "118", "151", "242", "25", "115", "76", "184", "228", "147", "27", "57", "183", "223", "257", "4", "146", "184", "212", "50", "137", "43", "201", "194", "265", "87", "4", "198", "110", "185", "261", "232", "17", "68", "146", "190", "223", "43", "76", "147", "185", "242", "261", "27", "115", "151", "228", "87", "34", "137", "198", "50", "194", "257", "25", "232", "183");
|
||||
private final CardRun commonC = new CardRun(true, "16", "62", "132", "152", "206", "12", "54", "129", "163", "234", "16", "97", "166", "111", "241", "152", "8", "81", "99", "273", "205", "170", "29", "89", "141", "166", "93", "234", "45", "132", "163", "62", "241", "29", "141", "154", "81", "218", "45", "129", "157", "93", "206", "54", "8", "154", "111", "218", "170", "12", "89", "99", "205", "97", "157");
|
||||
private final CardRun commonD = new CardRun(true, "22", "225", "153", "109", "79", "217", "140", "39", "164", "204", "51", "24", "138", "225", "41", "79", "100", "80", "164", "140", "52", "24", "236", "153", "47", "215", "101", "98", "100", "22", "70", "186", "40", "204", "47", "52", "127", "98", "138", "215", "80", "180", "51", "236", "109", "39", "127", "186", "41", "217", "70", "101", "180", "40", "273");
|
||||
private final CardRun uncommonA = new CardRun(false, "5", "102", "155", "7", "55", "11", "162", "59", "207", "208", "13", "112", "64", "165", "167", "169", "67", "18", "174", "117", "119", "26", "224", "226", "122", "72", "73", "130", "136", "188", "82", "42", "237", "239", "94", "46", "275", "277", "279", "243");
|
||||
private final CardRun uncommonB = new CardRun(false, "53", "199", "158", "160", "9", "200", "10", "58", "60", "61", "63", "113", "168", "114", "116", "171", "172", "216", "19", "220", "221", "182", "222", "28", "124", "125", "74", "36", "235", "38", "139", "86", "142", "193", "144", "195", "276", "278", "49", "245");
|
||||
private final CardRun rare = new CardRun(false, "1", "266", "2", "150", "149", "267", "3", "104", "6", "246", "105", "159", "202", "106", "254", "56", "203", "255", "256", "247", "107", "209", "210", "65", "14", "66", "248", "15", "213", "268", "69", "173", "175", "21", "249", "176", "269", "219", "178", "179", "71", "120", "121", "123", "230", "30", "31", "75", "270", "250", "131", "187", "133", "233", "135", "37", "259", "83", "271", "85", "272", "88", "274", "192", "92", "251", "262", "145", "44", "263", "238", "264", "240", "280", "95", "196", "281", "252", "244", "253");
|
||||
|
||||
private final BoosterStructure AAAAAACCCCC = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA, commonA,
|
||||
commonC, commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure AAAAAADDDDD = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA, commonA,
|
||||
commonD, commonD, commonD, commonD, commonD
|
||||
);
|
||||
private final BoosterStructure BBBBBBCCCCC = new BoosterStructure(
|
||||
commonB, commonB, commonB, commonB, commonB, commonB,
|
||||
commonC, commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure BBBBBBDDDDD = new BoosterStructure(
|
||||
commonB, commonB, commonB, commonB, commonB, commonB,
|
||||
commonD, commonD, commonD, commonD, commonD
|
||||
);
|
||||
private final BoosterStructure ABB = new BoosterStructure(uncommonA, uncommonB, uncommonB);
|
||||
private final BoosterStructure AAB = new BoosterStructure(uncommonA, uncommonA, uncommonB);
|
||||
|
||||
private final BoosterStructure R1 = new BoosterStructure(rare);
|
||||
|
||||
private final RarityConfiguration commonRuns = new RarityConfiguration(
|
||||
AAAAAACCCCC, AAAAAADDDDD, BBBBBBCCCCC, BBBBBBDDDDD
|
||||
);
|
||||
|
||||
private final RarityConfiguration uncommonRuns = new RarityConfiguration(
|
||||
AAB, ABB
|
||||
);
|
||||
|
||||
private final RarityConfiguration rareRuns = new RarityConfiguration(R1);
|
||||
|
||||
@Override
|
||||
public List<String> makeBooster() {
|
||||
List<String> booster = new ArrayList<>();
|
||||
booster.addAll(commonRuns.getNext().makeRun());
|
||||
booster.addAll(uncommonRuns.getNext().makeRun());
|
||||
booster.addAll(rareRuns.getNext().makeRun());
|
||||
return booster;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ package mage.sets;
|
|||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
import mage.collation.BoosterCollator;
|
||||
import mage.collation.BoosterStructure;
|
||||
import mage.collation.CardRun;
|
||||
import mage.collation.RarityConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class NewPhyrexia extends ExpansionSet {
|
||||
|
||||
|
|
@ -198,4 +205,62 @@ public final class NewPhyrexia extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Wing Splicer", 50, Rarity.UNCOMMON, mage.cards.w.WingSplicer.class));
|
||||
cards.add(new SetCardInfo("Xenograft", 51, Rarity.RARE, mage.cards.x.Xenograft.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoosterCollator createCollator() {
|
||||
return new NewPhyrexiaCollator();
|
||||
}
|
||||
}
|
||||
|
||||
// Booster collation info from https://www.lethe.xyz/mtg/collation/nph.html
|
||||
class NewPhyrexiaCollator implements BoosterCollator {
|
||||
private final CardRun commonA = new CardRun(true, "34", "99", "111", "131", "66", "30", "22", "89", "139", "113", "55", "2", "48", "131", "114", "93", "25", "76", "35", "138", "111", "83", "11", "55", "120", "99", "43", "150", "125", "22", "83", "75", "21", "34", "113", "140", "14", "60", "94", "11", "124", "48", "139", "120", "25", "75", "94", "30", "125", "140", "2", "145", "66", "89", "43", "114", "14", "138", "60", "35", "93", "124", "76", "21", "145", "150");
|
||||
private final CardRun commonB = new CardRun(true, "122", "45", "69", "84", "163", "26", "96", "110", "67", "40", "100", "24", "149", "36", "69", "116", "79", "61", "26", "151", "46", "92", "13", "108", "45", "63", "100", "67", "163", "24", "29", "79", "46", "96", "63", "19", "40", "52", "110", "149", "84", "136", "29", "13", "122", "61", "151", "108", "36", "92", "52", "116", "136", "19");
|
||||
private final CardRun uncommonA = new CardRun(true, "5", "56", "134", "126", "102", "28", "53", "8", "134", "107", "154", "56", "118", "156", "102", "12", "133", "107", "33", "165", "53", "154", "126", "91", "142", "8", "33", "112", "77", "90", "129", "15", "39", "152", "64", "90", "142", "12", "112", "32", "77", "129", "101", "117", "156", "72", "5", "101", "39", "117", "165", "3", "64", "133", "147", "91", "3", "32", "72", "147", "86", "15", "118", "28", "152", "86");
|
||||
private final CardRun uncommonB = new CardRun(true, "160", "105", "144", "123", "59", "27", "47", "103", "144", "97", "141", "157", "121", "38", "82", "57", "23", "157", "16", "49", "82", "58", "10", "85", "155", "103", "38", "153", "78", "59", "155", "27", "7", "160", "50", "58", "141", "78", "123", "50", "85", "57", "97", "23", "47", "70", "7", "105", "10", "49", "70", "153", "121", "16");
|
||||
private final CardRun rare = new CardRun(false, "130", "104", "104", "4", "4", "80", "80", "132", "132", "6", "6", "54", "54", "81", "81", "31", "31", "106", "106", "9", "135", "109", "109", "62", "62", "137", "137", "87", "87", "37", "128", "128", "1", "143", "143", "65", "65", "115", "115", "88", "88", "146", "146", "17", "17", "148", "148", "41", "41", "42", "42", "68", "119", "119", "18", "18", "71", "71", "44", "44", "20", "20", "73", "95", "95", "158", "158", "159", "159", "74", "74", "161", "162", "162", "164", "164", "98", "127", "51", "51");
|
||||
private final CardRun land = new CardRun(false, "166", "167", "168", "169", "170", "171", "172", "173", "174", "175");
|
||||
|
||||
private final BoosterStructure AAAAAABBBB = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA, commonA,
|
||||
commonB, commonB, commonB, commonB
|
||||
);
|
||||
private final BoosterStructure AAAAABBBBB = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA,
|
||||
commonB, commonB, commonB, commonB, commonB
|
||||
);
|
||||
private final BoosterStructure ABB = new BoosterStructure(uncommonA, uncommonB, uncommonB);
|
||||
private final BoosterStructure AAB = new BoosterStructure(uncommonA, uncommonA, uncommonB);
|
||||
|
||||
private final BoosterStructure R1 = new BoosterStructure(rare);
|
||||
private final BoosterStructure L1 = new BoosterStructure(land);
|
||||
|
||||
// In order for equal numbers of each common to exist, the average booster must contain:
|
||||
// 5.5 A uncommons (11 / 2)
|
||||
// 4.5 B uncommons (9 / 2)
|
||||
private final RarityConfiguration commonRuns = new RarityConfiguration(
|
||||
AAAAAABBBB, AAAAABBBBB
|
||||
);
|
||||
|
||||
// In order for equal numbers of each common to exist, the average booster must contain:
|
||||
// 1.65 A uncommons (33 / 20)
|
||||
// 1.35 B uncommons (27 / 20)
|
||||
private final RarityConfiguration uncommonRuns = new RarityConfiguration(
|
||||
AAB, AAB, AAB, AAB, AAB, AAB, AAB, AAB, AAB, AAB,
|
||||
AAB, AAB, AAB,
|
||||
ABB, ABB, ABB, ABB, ABB, ABB, ABB
|
||||
);
|
||||
|
||||
private final RarityConfiguration rareRuns = new RarityConfiguration(R1);
|
||||
private final RarityConfiguration landRuns = new RarityConfiguration(L1);
|
||||
|
||||
@Override
|
||||
public List<String> makeBooster() {
|
||||
List<String> booster = new ArrayList<>();
|
||||
booster.addAll(commonRuns.getNext().makeRun());
|
||||
booster.addAll(uncommonRuns.getNext().makeRun());
|
||||
booster.addAll(rareRuns.getNext().makeRun());
|
||||
booster.addAll(landRuns.getNext().makeRun());
|
||||
return booster;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,13 @@ package mage.sets;
|
|||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
import mage.collation.BoosterCollator;
|
||||
import mage.collation.BoosterStructure;
|
||||
import mage.collation.CardRun;
|
||||
import mage.collation.RarityConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
|
|
@ -508,8 +514,81 @@ public final class PhyrexiaAllWillBeOne extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Zopandrel, Hunger Dominus", 458, Rarity.MYTHIC, mage.cards.z.ZopandrelHungerDominus.class, NON_FULL_USE_VARIOUS));
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public BoosterCollator createCollator() {
|
||||
// return new PhyrexiaAllWillBeOneCollator();
|
||||
// }
|
||||
@Override
|
||||
public BoosterCollator createCollator() {
|
||||
return new PhyrexiaAllWillBeOneCollator();
|
||||
}
|
||||
}
|
||||
|
||||
// Booster collation info from https://www.lethe.xyz/mtg/collation/one.html
|
||||
// Using Japanese collation for common, no collation for uncommons
|
||||
// Using 2:1 for each rare:mythic which results in (1/7) 14.29% mythic packs, matching the advertised ~14%
|
||||
class PhyrexiaAllWillBeOneCollator implements BoosterCollator {
|
||||
private final CardRun commonA = new CardRun(true, "54", "251", "44", "77", "243", "49", "228", "45", "231", "55", "260", "58", "60", "238", "65", "187", "54", "253", "59", "252", "52", "44", "224", "62", "251", "50", "139", "48", "236", "77", "238", "59", "53", "253", "65", "50", "187", "60", "228", "48", "260", "55", "251", "53", "231", "58", "252", "49", "243", "45", "224", "52", "236", "54", "139", "62", "44", "252", "58", "48", "238", "55", "243", "59", "139", "52", "260", "62", "54", "231", "50", "228", "44", "253", "77", "224", "49", "251", "65", "60", "236", "53", "187", "45", "228", "55", "52", "253", "50", "260", "77", "236", "58", "238", "45", "252", "65", "139", "49", "187", "59", "243", "48", "62", "231", "60", "53", "224");
|
||||
private final CardRun commonB = new CardRun(true, "16", "94", "111", "15", "7", "97", "12", "96", "102", "20", "120", "110", "9", "25", "103", "6", "40", "94", "4", "247", "117", "13", "137", "88", "39", "225", "109", "22", "151", "116", "28", "226", "92", "21", "12", "97", "8", "20", "111", "261", "39", "89", "28", "36", "117", "21", "120", "116", "8", "247", "103", "13", "40", "110", "22", "16", "102", "225", "4", "88", "151", "9", "109", "226", "7", "96", "137", "25", "92", "36", "6", "116", "261", "15", "109", "21", "39", "110", "16", "13", "102", "22", "137", "94", "25", "15", "111", "247", "8", "89", "12", "225", "117", "9", "120", "97", "7", "261", "103", "36", "40", "88", "28", "20", "92", "226", "4", "96", "151", "6", "89");
|
||||
private final CardRun commonC = new CardRun(true, "81", "165", "147", "188", "286", "126", "162", "173", "130", "180", "66", "122", "164", "157", "123", "160", "85", "156", "174", "237", "121", "170", "130", "188", "123", "185", "290", "122", "181", "179", "133", "157", "81", "135", "180", "182", "148", "66", "170", "126", "32", "162", "156", "235", "173", "141", "183", "80", "147", "174", "160", "131", "165", "164", "135", "32", "177", "155", "289", "180", "121", "181", "80", "131", "179", "235", "133", "188", "81", "130", "170", "121", "174", "80", "123", "177", "148", "182", "292", "165", "86", "141", "160", "237", "155", "185", "173", "148", "235", "164", "122", "287", "162", "135", "86", "157", "156", "183", "141", "177", "237", "133", "179", "185", "126", "85", "295", "155", "182", "183", "131");
|
||||
private final CardRun uncommon = new CardRun(false, "1", "79", "2", "3", "158", "41", "223", "119", "83", "5", "197", "124", "161", "198", "199", "87", "127", "200", "46", "91", "167", "168", "129", "93", "51", "132", "134", "136", "14", "230", "171", "172", "17", "18", "140", "64", "234", "142", "99", "212", "100", "101", "176", "26", "143", "178", "29", "30", "239", "106", "144", "67", "31", "146", "240", "107", "215", "68", "108", "216", "35", "184", "217", "69", "70", "72", "73", "74", "190", "76", "191", "152", "112", "113", "37", "193", "194", "220", "221", "78");
|
||||
private final CardRun rare = new CardRun(false, "118", "82", "82", "222", "222", "196", "248", "248", "84", "84", "42", "42", "159", "159", "43", "43", "125", "163", "163", "249", "249", "250", "250", "128", "128", "90", "10", "47", "47", "166", "166", "201", "201", "95", "95", "202", "202", "229", "229", "169", "169", "56", "57", "203", "203", "204", "204", "98", "98", "205", "205", "19", "19", "206", "206", "138", "138", "207", "208", "208", "209", "209", "61", "61", "210", "210", "63", "63", "232", "232", "254", "254", "23", "233", "233", "211", "175", "24", "24", "213", "213", "104", "104", "105", "27", "257", "257", "145", "145", "214", "214", "258", "258", "33", "33", "34", "34", "149", "149", "150", "241", "241", "242", "244", "245", "245", "71", "11", "11", "227", "227", "255", "255", "256", "256", "259", "259", "186", "186", "189", "218", "218", "75", "75", "153", "153", "192", "192", "219", "219", "154", "154", "114", "114", "115", "38", "38", "246", "246", "195");
|
||||
private final CardRun land = new CardRun(false, "262", "263", "264", "265", "266", "267", "268", "269", "270", "271", "272", "273", "274", "275", "276", "365", "366", "367", "368", "369");
|
||||
|
||||
private final BoosterStructure AABBBBCCCC = new BoosterStructure(
|
||||
commonA, commonA,
|
||||
commonB, commonB, commonB, commonB,
|
||||
commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure AAABBBCCCC = new BoosterStructure(
|
||||
commonA, commonA, commonA,
|
||||
commonB, commonB, commonB,
|
||||
commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure AAABBBBCCC = new BoosterStructure(
|
||||
commonA, commonA, commonA,
|
||||
commonB, commonB, commonB, commonB,
|
||||
commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure U3 = new BoosterStructure(uncommon, uncommon, uncommon);
|
||||
private final BoosterStructure R1 = new BoosterStructure(rare);
|
||||
private final BoosterStructure L1 = new BoosterStructure(land);
|
||||
|
||||
// In order for equal numbers of each common to exist, the average booster must contain:
|
||||
// 2.67 A commons (270 / 101)
|
||||
// 3.66 B commons (370 / 101)
|
||||
// 3.66 C commons (370 / 101)
|
||||
private final RarityConfiguration commonRuns = new RarityConfiguration(
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AABBBBCCCC, AABBBBCCCC, AABBBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBCCCC, AAABBBCCCC, AAABBBCCCC, AAABBBCCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC,
|
||||
AAABBBBCCC, AAABBBBCCC, AAABBBBCCC, AAABBBBCCC
|
||||
);
|
||||
|
||||
private final RarityConfiguration uncommonRuns = new RarityConfiguration(U3);
|
||||
private final RarityConfiguration rareRuns = new RarityConfiguration(R1);
|
||||
private final RarityConfiguration landRuns = new RarityConfiguration(L1);
|
||||
|
||||
@Override
|
||||
public List<String> makeBooster() {
|
||||
List<String> booster = new ArrayList<>();
|
||||
booster.addAll(commonRuns.getNext().makeRun());
|
||||
booster.addAll(uncommonRuns.getNext().makeRun());
|
||||
booster.addAll(rareRuns.getNext().makeRun());
|
||||
booster.addAll(landRuns.getNext().makeRun());
|
||||
return booster;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ package mage.sets;
|
|||
import mage.cards.ExpansionSet;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
import mage.collation.BoosterCollator;
|
||||
import mage.collation.BoosterStructure;
|
||||
import mage.collation.CardRun;
|
||||
import mage.collation.RarityConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
|
|
@ -328,4 +335,62 @@ public final class Shadowmoor extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Wound Reflection", 81, Rarity.RARE, mage.cards.w.WoundReflection.class));
|
||||
cards.add(new SetCardInfo("Zealous Guardian", 157, Rarity.COMMON, mage.cards.z.ZealousGuardian.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoosterCollator createCollator() {
|
||||
return new ShadowmoorCollator();
|
||||
}
|
||||
}
|
||||
|
||||
// Booster collation info from https://www.lethe.xyz/mtg/collation/shm.html
|
||||
// order not known for uncommon runs, but card division is
|
||||
// pack distribution for uncommons not specified, assuming AAB ABB as in Onslaught
|
||||
class ShadowmoorCollator implements BoosterCollator {
|
||||
private final CardRun commonA = new CardRun(true, "238", "263", "230", "39", "133", "67", "102", "212", "249", "11", "30", "196", "82", "125", "242", "41", "182", "100", "113", "11", "178", "196", "22", "102", "238", "270", "232", "39", "173", "86", "133", "60", "148", "178", "194", "85", "125", "30", "22", "32", "182", "82", "212", "270", "242", "44", "67", "85", "235", "215", "230", "41", "60", "86", "113", "263", "232", "44", "194", "100", "235", "249", "148", "32", "173", "215");
|
||||
private final CardRun commonB = new CardRun(true, "20", "121", "218", "77", "177", "247", "149", "109", "136", "164", "195", "150", "239", "124", "213", "80", "177", "268", "138", "216", "66", "200", "139", "149", "259", "110", "152", "187", "166", "165", "20", "216", "101", "64", "45", "268", "3", "224", "195", "66", "139", "166", "152", "121", "101", "164", "150", "259", "138", "110", "218", "64", "124", "136", "239", "224", "213", "77", "45", "247", "3", "109", "200", "165", "80", "187");
|
||||
private final CardRun commonC = new CardRun(true, "265", "13", "52", "95", "115", "79", "27", "46", "88", "132", "59", "13", "246", "52", "105", "55", "10", "161", "193", "116", "56", "1", "54", "130", "265", "105", "240", "55", "27", "170", "207", "246", "185", "116", "10", "46", "95", "240", "79", "4", "170", "193", "115", "258", "59", "1", "161", "88", "130", "185", "4", "54", "207", "132", "56");
|
||||
private final CardRun commonD = new CardRun(true, "107", "78", "262", "24", "36", "175", "96", "51", "8", "118", "191", "217", "226", "6", "157", "71", "91", "15", "210", "36", "258", "84", "211", "155", "175", "250", "31", "91", "78", "118", "51", "6", "107", "120", "71", "262", "217", "76", "8", "48", "191", "211", "31", "24", "120", "96", "250", "15", "157", "76", "84", "210", "48", "155", "226");
|
||||
private final CardRun uncommonA = new CardRun(false, "28", "57", "83", "58", "61", "63", "34", "225", "35", "160", "112", "38", "206", "208", "253", "69", "94", "168", "9", "273", "255", "256", "274", "231", "171", "14", "275", "276", "17", "103", "127", "236", "19", "261", "128", "279", "106", "197", "267", "108");
|
||||
private final CardRun uncommonB = new CardRun(false, "2", "180", "29", "203", "62", "37", "205", "92", "114", "141", "117", "251", "189", "119", "254", "70", "167", "97", "229", "190", "43", "144", "192", "145", "18", "146", "147", "174", "241", "23", "264", "219", "220", "154", "199", "131", "266", "179", "269", "244");
|
||||
private final CardRun rare = new CardRun(false, "181", "137", "202", "5", "248", "158", "33", "87", "89", "183", "204", "184", "159", "111", "65", "90", "140", "186", "271", "227", "188", "93", "162", "163", "142", "272", "7", "252", "228", "68", "209", "40", "42", "98", "99", "122", "12", "169", "72", "143", "123", "277", "172", "233", "16", "234", "257", "73", "74", "126", "47", "75", "104", "260", "278", "237", "49", "214", "21", "50", "129", "198", "280", "151", "176", "153", "53", "25", "201", "221", "222", "243", "245", "26", "134", "281", "135", "156", "223", "81");
|
||||
|
||||
private final BoosterStructure AAAAAACCCCC = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA, commonA,
|
||||
commonC, commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure AAAAAADDDDD = new BoosterStructure(
|
||||
commonA, commonA, commonA, commonA, commonA, commonA,
|
||||
commonD, commonD, commonD, commonD, commonD
|
||||
);
|
||||
private final BoosterStructure BBBBBBCCCCC = new BoosterStructure(
|
||||
commonB, commonB, commonB, commonB, commonB, commonB,
|
||||
commonC, commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure BBBBBBDDDDD = new BoosterStructure(
|
||||
commonB, commonB, commonB, commonB, commonB, commonB,
|
||||
commonD, commonD, commonD, commonD, commonD
|
||||
);
|
||||
private final BoosterStructure ABB = new BoosterStructure(uncommonA, uncommonB, uncommonB);
|
||||
private final BoosterStructure AAB = new BoosterStructure(uncommonA, uncommonA, uncommonB);
|
||||
|
||||
private final BoosterStructure R1 = new BoosterStructure(rare);
|
||||
|
||||
private final RarityConfiguration commonRuns = new RarityConfiguration(
|
||||
AAAAAACCCCC, AAAAAADDDDD, BBBBBBCCCCC, BBBBBBDDDDD
|
||||
);
|
||||
|
||||
private final RarityConfiguration uncommonRuns = new RarityConfiguration(
|
||||
AAB, ABB
|
||||
);
|
||||
|
||||
private final RarityConfiguration rareRuns = new RarityConfiguration(R1);
|
||||
|
||||
@Override
|
||||
public List<String> makeBooster() {
|
||||
List<String> booster = new ArrayList<>();
|
||||
booster.addAll(commonRuns.getNext().makeRun());
|
||||
booster.addAll(uncommonRuns.getNext().makeRun());
|
||||
booster.addAll(rareRuns.getNext().makeRun());
|
||||
return booster;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import mage.cards.repository.CardInfo;
|
|||
import mage.constants.Rarity;
|
||||
import mage.constants.SetType;
|
||||
import mage.util.RandomUtil;
|
||||
import mage.collation.BoosterCollator;
|
||||
import mage.collation.BoosterStructure;
|
||||
import mage.collation.CardRun;
|
||||
import mage.collation.RarityConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -509,20 +513,92 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<CardInfo> findSpecialCardsByRarity(Rarity rarity) {
|
||||
if (rarity == Rarity.RARE || rarity == Rarity.MYTHIC) {
|
||||
return new ArrayList<>(); // Rare/Mythic DFCs are not special cards here
|
||||
} else {
|
||||
return super.findSpecialCardsByRarity(rarity);
|
||||
// this accounts for 7 caves in the land slot, as well as the common/uncommon DFCs
|
||||
}
|
||||
public BoosterCollator createCollator() {
|
||||
return new TheLostCavernsOfIxalanCollator();
|
||||
}
|
||||
}
|
||||
|
||||
// Booster collation info from https://www.lethe.xyz/mtg/collation/lci.html
|
||||
// Using Japanese collation
|
||||
// Using 1:2 ratio for individual dfc uncommon:common - as per shown sheet - differs from text description
|
||||
// Using 5:3 ratio for individual nonbasic:basic - matches both text desciption and shown sheet
|
||||
class TheLostCavernsOfIxalanCollator implements BoosterCollator {
|
||||
private final CardRun commonA = new CardRun(true, "174", "248", "175", "166", "192", "206", "199", "205", "177", "138", "203", "210", "200", "192", "175", "206", "201", "250", "177", "174", "200", "205", "203", "210", "136", "202", "214", "182", "138", "218", "190", "248", "199", "166", "210", "192", "214", "174", "218", "182", "259", "190", "199", "248", "200", "203", "138", "177", "250", "202", "205", "166", "175", "259", "201", "136", "206", "250", "192", "203", "177", "248", "199", "174", "136", "205", "214", "166", "206", "201", "218", "202", "138", "200", "175", "182", "259", "190", "210", "192", "218", "166", "200", "174", "199", "250", "205", "190", "210", "201", "136", "206", "182", "138", "202", "175", "248", "177", "259", "214", "203", "201", "250", "190", "182", "218", "259", "202", "136", "214");
|
||||
private final CardRun commonB = new CardRun(true, "46", "140", "49", "131", "77", "149", "209", "75", "167", "84", "169", "66", "172", "71", "73", "163", "253", "68", "144", "57", "82", "131", "246", "45", "132", "64", "207", "151", "85", "154", "49", "140", "46", "168", "72", "70", "142", "53", "159", "69", "160", "85", "167", "207", "64", "151", "46", "132", "73", "163", "71", "75", "154", "253", "70", "160", "49", "82", "131", "246", "84", "142", "77", "209", "168", "68", "172", "69", "140", "53", "149", "72", "66", "169", "45", "159", "57", "144", "82", "168", "209", "66", "149", "84", "142", "85", "172", "69", "77", "160", "246", "68", "154", "57", "73", "144", "253", "45", "132", "75", "207", "169", "70", "163", "71", "159", "72", "151", "53", "64", "167");
|
||||
private final CardRun commonC = new CardRun(true, "116", "2", "99", "15", "90", "13", "118", "18", "101", "40", "130", "31", "106", "37", "110", "9", "117", "28", "89", "24", "100", "11", "95", "35", "114", "38", "104", "4", "109", "3", "90", "11", "255", "105", "15", "89", "31", "110", "40", "118", "30", "119", "13", "99", "28", "117", "2", "100", "7", "106", "3", "116", "38", "101", "18", "112", "24", "130", "27", "109", "4", "104", "9", "114", "35", "95", "37", "118", "31", "255", "104", "28", "106", "3", "130", "9", "90", "4", "99", "40", "119", "18", "105", "38", "116", "27", "109", "7", "100", "2", "114", "35", "95", "11", "110", "24", "112", "30", "117", "13", "101", "15", "89", "37", "119", "27", "255", "105", "30", "112", "7");
|
||||
private final CardRun dfc = new CardRun(false, "6", "146", "108", "155", "155", "60", "60", "195", "197", "197", "62", "233", "29", "29", "164", "36", "262", "128", "128", "217", "129", "83");
|
||||
private final CardRun uncommonA = new CardRun(false, "65", "65", "65", "74", "74", "74", "76", "76", "76", "78", "78", "405", "79", "79", "79", "86", "86", "86");
|
||||
private final CardRun uncommonB = new CardRun(true, "254", "33", "48", "23", "58", "286", "96", "251", "25", "111", "51", "5", "125", "8", "124", "186", "22", "102", "261", "87", "272", "107", "59", "120", "278", "19", "103", "42", "93", "21", "247", "33", "48", "111", "10", "50", "96", "23", "54", "286", "58", "17", "254", "213", "124", "8", "252", "59", "102", "25", "247", "51", "5", "125", "251", "107", "42", "93", "19", "103", "186", "22", "87", "278", "21", "261", "120", "272", "254", "17", "54", "252", "50", "10", "213", "48", "33", "58", "286", "96", "23", "51", "251", "124", "8", "125", "5", "102", "25", "59", "120", "247", "107", "186", "22", "272", "87", "261", "103", "278", "19", "93", "21", "111", "42", "252", "17", "54", "213", "10", "50");
|
||||
private final CardRun uncommonC = new CardRun(true, "245", "141", "301", "180", "230", "150", "220", "147", "194", "227", "148", "178", "139", "184", "260", "322", "263", "150", "187", "303", "198", "232", "183", "139", "270", "97", "173", "16", "187", "263", "198", "141", "298", "162", "232", "91", "173", "230", "143", "180", "170", "184", "242", "226", "147", "215", "320", "224", "187", "260", "236", "263", "143", "184", "242", "270", "245", "183", "147", "216", "236", "133", "224", "215", "310", "152", "302", "143", "331", "97", "178", "306", "323", "304", "198", "162", "329", "133", "312", "148", "215", "91", "170", "260", "179", "226", "194", "165", "16", "216", "97", "227", "152", "270", "150", "179", "139", "91", "170", "194", "165", "16", "141", "180", "152", "179", "220", "178", "173", "325", "148");
|
||||
private final CardRun rare = new CardRun(false, "219", "219", "1", "1", "88", "44", "44", "221", "221", "223", "223", "176", "176", "92", "134", "47", "47", "135", "135", "137", "137", "94", "94", "269", "249", "98", "98", "181", "181", "228", "228", "52", "52", "145", "145", "271", "271", "12", "12", "14", "14", "185", "229", "188", "188", "153", "153", "189", "191", "191", "156", "156", "193", "193", "196", "196", "231", "231", "61", "61", "20", "20", "157", "157", "63", "63", "256", "256", "234", "234", "158", "204", "67", "26", "237", "237", "161", "161", "113", "113", "208", "208", "115", "115", "238", "32", "280", "280", "281", "281", "282", "282", "283", "283", "284", "284", "258", "258", "239", "34", "34", "211", "211", "121", "121", "240", "241", "241", "122", "122", "123", "123", "80", "80", "285", "285", "126", "126", "264", "264", "127", "127", "222", "225", "225", "55", "56", "56", "257", "235", "212", "39", "39", "265", "265", "266", "266", "81", "81", "267", "267", "171", "171", "41", "41", "243", "244", "244", "43", "43");
|
||||
private final CardRun land = new CardRun(false, "268", "268", "268", "268", "268", "273", "273", "273", "273", "273", "274", "274", "274", "274", "274", "275", "275", "275", "275", "275", "276", "276", "276", "276", "276", "277", "277", "277", "277", "277", "279", "279", "279", "279", "279", "287", "287", "287", "288", "288", "288", "289", "289", "289", "290", "290", "290", "291", "291", "291", "393", "393", "393", "394", "394", "394", "395", "395", "395", "396", "396", "396", "397", "397", "397", "398", "398", "398", "399", "399", "399", "400", "400", "400", "401", "401", "401", "402", "402", "402");
|
||||
|
||||
private final BoosterStructure AABBBCCCC = new BoosterStructure(
|
||||
commonA, commonA,
|
||||
commonB, commonB, commonB,
|
||||
commonC, commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure AABBBBCCC = new BoosterStructure(
|
||||
commonA, commonA,
|
||||
commonB, commonB, commonB, commonB,
|
||||
commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure AAABBBCCC = new BoosterStructure(
|
||||
commonA, commonA, commonA,
|
||||
commonB, commonB, commonB,
|
||||
commonC, commonC, commonC
|
||||
);
|
||||
private final BoosterStructure BCC = new BoosterStructure(uncommonB, uncommonC, uncommonC);
|
||||
private final BoosterStructure BBC = new BoosterStructure(uncommonB, uncommonB, uncommonC);
|
||||
private final BoosterStructure ABC = new BoosterStructure(uncommonA, uncommonB, uncommonC);
|
||||
|
||||
private final BoosterStructure D1 = new BoosterStructure(dfc);
|
||||
private final BoosterStructure R1 = new BoosterStructure(rare);
|
||||
private final BoosterStructure L1 = new BoosterStructure(land);
|
||||
|
||||
// In order for equal numbers of each common to exist, the average booster must contain:
|
||||
// 2.06250 A commons (66 / 32)
|
||||
// 3.46875 B commons (111 / 32)
|
||||
// 3.46875 C commons (111 / 32)
|
||||
private final RarityConfiguration commonRuns = new RarityConfiguration(
|
||||
AABBBCCCC, AABBBCCCC, AABBBCCCC, AABBBCCCC, AABBBCCCC,
|
||||
AABBBCCCC, AABBBCCCC, AABBBCCCC, AABBBCCCC, AABBBCCCC,
|
||||
AABBBCCCC, AABBBCCCC, AABBBCCCC, AABBBCCCC, AABBBCCCC,
|
||||
AABBBBCCC, AABBBBCCC, AABBBBCCC, AABBBBCCC, AABBBBCCC,
|
||||
AABBBBCCC, AABBBBCCC, AABBBBCCC, AABBBBCCC, AABBBBCCC,
|
||||
AABBBBCCC, AABBBBCCC, AABBBBCCC, AABBBBCCC, AABBBBCCC,
|
||||
AAABBBCCC, AAABBBCCC
|
||||
);
|
||||
|
||||
// In order for equal numbers of each common to exist, the average booster must contain:
|
||||
// 0.2250 A uncommons (18 / 80)
|
||||
// 1.3875 B uncommons (111 / 80)
|
||||
// 1.3875 C uncommons (111 / 80)
|
||||
private final RarityConfiguration uncommonRuns = new RarityConfiguration(
|
||||
BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC,
|
||||
BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC,
|
||||
BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC, BCC,
|
||||
BCC,
|
||||
BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC,
|
||||
BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC,
|
||||
BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC, BBC,
|
||||
BBC,
|
||||
ABC, ABC, ABC, ABC, ABC, ABC, ABC, ABC, ABC, ABC,
|
||||
ABC, ABC, ABC, ABC, ABC, ABC, ABC, ABC
|
||||
);
|
||||
|
||||
private final RarityConfiguration dfcRuns = new RarityConfiguration(D1);
|
||||
private final RarityConfiguration rareRuns = new RarityConfiguration(R1);
|
||||
private final RarityConfiguration landRuns = new RarityConfiguration(L1);
|
||||
|
||||
@Override
|
||||
protected void addDoubleFace(List<Card> booster) {
|
||||
int rarityKey = RandomUtil.nextInt((5 * 3) + 12); // 5 C, 12 U - assume commons three times the frequency as uncommons
|
||||
Rarity rarity = (rarityKey > 12) ? Rarity.COMMON : Rarity.UNCOMMON;
|
||||
addToBooster(booster, getSpecialCardsByRarity(rarity));
|
||||
public List<String> makeBooster() {
|
||||
List<String> booster = new ArrayList<>();
|
||||
booster.addAll(commonRuns.getNext().makeRun());
|
||||
booster.addAll(dfcRuns.getNext().makeRun());
|
||||
booster.addAll(uncommonRuns.getNext().makeRun());
|
||||
booster.addAll(rareRuns.getNext().makeRun());
|
||||
booster.addAll(landRuns.getNext().makeRun());
|
||||
return booster;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -20,20 +20,24 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
this.hasBasicLands = false;
|
||||
|
||||
cards.add(new SetCardInfo("Ajani's Chosen", 59, Rarity.RARE, mage.cards.a.AjanisChosen.class));
|
||||
cards.add(new SetCardInfo("Alela, Cunning Conqueror", 3, Rarity.MYTHIC, mage.cards.a.AlelaCunningConqueror.class));
|
||||
cards.add(new SetCardInfo("Alela, Cunning Conqueror", 3, Rarity.MYTHIC, mage.cards.a.AlelaCunningConqueror.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Alela, Cunning Conqueror", 34, Rarity.MYTHIC, mage.cards.a.AlelaCunningConqueror.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ancestral Mask", 119, Rarity.COMMON, mage.cards.a.AncestralMask.class));
|
||||
cards.add(new SetCardInfo("Angelic Destiny", 60, Rarity.MYTHIC, mage.cards.a.AngelicDestiny.class));
|
||||
cards.add(new SetCardInfo("Arcane Denial", 84, Rarity.COMMON, mage.cards.a.ArcaneDenial.class));
|
||||
cards.add(new SetCardInfo("Arcane Signet", 145, Rarity.COMMON, mage.cards.a.ArcaneSignet.class));
|
||||
cards.add(new SetCardInfo("Archmage of Echoes", 9, Rarity.RARE, mage.cards.a.ArchmageOfEchoes.class));
|
||||
cards.add(new SetCardInfo("Archmage of Echoes", 9, Rarity.RARE, mage.cards.a.ArchmageOfEchoes.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Archmage of Echoes", 45, Rarity.RARE, mage.cards.a.ArchmageOfEchoes.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Archon of Sun's Grace", 61, Rarity.RARE, mage.cards.a.ArchonOfSunsGrace.class));
|
||||
cards.add(new SetCardInfo("Aura Gnarlid", 120, Rarity.COMMON, mage.cards.a.AuraGnarlid.class));
|
||||
cards.add(new SetCardInfo("Austere Command", 62, Rarity.RARE, mage.cards.a.AustereCommand.class));
|
||||
cards.add(new SetCardInfo("Bear Umbra", 121, Rarity.RARE, mage.cards.b.BearUmbra.class));
|
||||
cards.add(new SetCardInfo("Blightwing Bandit", 13, Rarity.RARE, mage.cards.b.BlightwingBandit.class));
|
||||
cards.add(new SetCardInfo("Blightwing Bandit", 13, Rarity.RARE, mage.cards.b.BlightwingBandit.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blightwing Bandit", 49, Rarity.RARE, mage.cards.b.BlightwingBandit.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Bojuka Bog", 152, Rarity.COMMON, mage.cards.b.BojukaBog.class));
|
||||
cards.add(new SetCardInfo("Brazen Borrower", 85, Rarity.MYTHIC, mage.cards.b.BrazenBorrower.class));
|
||||
cards.add(new SetCardInfo("Brenard, Ginger Sculptor", 27, Rarity.MYTHIC, mage.cards.b.BrenardGingerSculptor.class));
|
||||
cards.add(new SetCardInfo("Brenard, Ginger Sculptor", 27, Rarity.MYTHIC, mage.cards.b.BrenardGingerSculptor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Brenard, Ginger Sculptor", 35, Rarity.MYTHIC, mage.cards.b.BrenardGingerSculptor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Canopy Vista", 153, Rarity.RARE, mage.cards.c.CanopyVista.class));
|
||||
cards.add(new SetCardInfo("Careful Cultivation", 122, Rarity.COMMON, mage.cards.c.CarefulCultivation.class));
|
||||
cards.add(new SetCardInfo("Castle Ardenvale", 154, Rarity.RARE, mage.cards.c.CastleArdenvale.class));
|
||||
|
|
@ -42,11 +46,16 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Cloud of Faeries", 86, Rarity.COMMON, mage.cards.c.CloudOfFaeries.class));
|
||||
cards.add(new SetCardInfo("Command Tower", 156, Rarity.COMMON, mage.cards.c.CommandTower.class));
|
||||
cards.add(new SetCardInfo("Consider", 87, Rarity.COMMON, mage.cards.c.Consider.class));
|
||||
cards.add(new SetCardInfo("Court of Ardenvale", 21, Rarity.RARE, mage.cards.c.CourtOfArdenvale.class));
|
||||
cards.add(new SetCardInfo("Court of Embereth", 24, Rarity.RARE, mage.cards.c.CourtOfEmbereth.class));
|
||||
cards.add(new SetCardInfo("Court of Garenbrig", 25, Rarity.RARE, mage.cards.c.CourtOfGarenbrig.class));
|
||||
cards.add(new SetCardInfo("Court of Locthwain", 23, Rarity.RARE, mage.cards.c.CourtOfLocthwain.class));
|
||||
cards.add(new SetCardInfo("Court of Vantress", 22, Rarity.RARE, mage.cards.c.CourtOfVantress.class));
|
||||
cards.add(new SetCardInfo("Court of Ardenvale", 21, Rarity.RARE, mage.cards.c.CourtOfArdenvale.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Ardenvale", 29, Rarity.RARE, mage.cards.c.CourtOfArdenvale.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Embereth", 24, Rarity.RARE, mage.cards.c.CourtOfEmbereth.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Embereth", 32, Rarity.RARE, mage.cards.c.CourtOfEmbereth.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Garenbrig", 25, Rarity.RARE, mage.cards.c.CourtOfGarenbrig.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Garenbrig", 33, Rarity.RARE, mage.cards.c.CourtOfGarenbrig.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Locthwain", 23, Rarity.RARE, mage.cards.c.CourtOfLocthwain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Locthwain", 31, Rarity.RARE, mage.cards.c.CourtOfLocthwain.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Vantress", 22, Rarity.RARE, mage.cards.c.CourtOfVantress.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Court of Vantress", 30, Rarity.RARE, mage.cards.c.CourtOfVantress.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Danitha Capashen, Paragon", 64, Rarity.UNCOMMON, mage.cards.d.DanithaCapashenParagon.class));
|
||||
cards.add(new SetCardInfo("Darkwater Catacombs", 157, Rarity.RARE, mage.cards.d.DarkwaterCatacombs.class));
|
||||
cards.add(new SetCardInfo("Daybreak Coronet", 65, Rarity.RARE, mage.cards.d.DaybreakCoronet.class));
|
||||
|
|
@ -57,12 +66,15 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Distant Melody", 89, Rarity.COMMON, mage.cards.d.DistantMelody.class));
|
||||
cards.add(new SetCardInfo("Eidolon of Blossoms", 124, Rarity.RARE, mage.cards.e.EidolonOfBlossoms.class));
|
||||
cards.add(new SetCardInfo("Eidolon of Countless Battles", 66, Rarity.RARE, mage.cards.e.EidolonOfCountlessBattles.class));
|
||||
cards.add(new SetCardInfo("Ellivere of the Wild Court", 2, Rarity.MYTHIC, mage.cards.e.EllivereOfTheWildCourt.class));
|
||||
cards.add(new SetCardInfo("Ellivere of the Wild Court", 2, Rarity.MYTHIC, mage.cards.e.EllivereOfTheWildCourt.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ellivere of the Wild Court", 36, Rarity.MYTHIC, mage.cards.e.EllivereOfTheWildCourt.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ellivere of the Wild Court", 57, Rarity.MYTHIC, mage.cards.e.EllivereOfTheWildCourt.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Enchantress's Presence", 125, Rarity.RARE, mage.cards.e.EnchantresssPresence.class));
|
||||
cards.add(new SetCardInfo("Ethereal Armor", 67, Rarity.COMMON, mage.cards.e.EtherealArmor.class));
|
||||
cards.add(new SetCardInfo("Exotic Orchard", 159, Rarity.RARE, mage.cards.e.ExoticOrchard.class));
|
||||
cards.add(new SetCardInfo("Fact or Fiction", 90, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class));
|
||||
cards.add(new SetCardInfo("Faerie Bladecrafter", 14, Rarity.RARE, mage.cards.f.FaerieBladecrafter.class));
|
||||
cards.add(new SetCardInfo("Faerie Bladecrafter", 14, Rarity.RARE, mage.cards.f.FaerieBladecrafter.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Faerie Bladecrafter", 50, Rarity.RARE, mage.cards.f.FaerieBladecrafter.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Faerie Conclave", 160, Rarity.UNCOMMON, mage.cards.f.FaerieConclave.class));
|
||||
cards.add(new SetCardInfo("Faerie Formation", 91, Rarity.RARE, mage.cards.f.FaerieFormation.class));
|
||||
cards.add(new SetCardInfo("Faerie Seer", 92, Rarity.COMMON, mage.cards.f.FaerieSeer.class));
|
||||
|
|
@ -71,10 +83,12 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Fortified Village", 161, Rarity.RARE, mage.cards.f.FortifiedVillage.class));
|
||||
cards.add(new SetCardInfo("Frantic Search", 93, Rarity.COMMON, mage.cards.f.FranticSearch.class));
|
||||
cards.add(new SetCardInfo("Generous Gift", 68, Rarity.UNCOMMON, mage.cards.g.GenerousGift.class));
|
||||
cards.add(new SetCardInfo("Giant Inheritance", 17, Rarity.RARE, mage.cards.g.GiantInheritance.class));
|
||||
cards.add(new SetCardInfo("Giant Inheritance", 17, Rarity.RARE, mage.cards.g.GiantInheritance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Giant Inheritance", 53, Rarity.RARE, mage.cards.g.GiantInheritance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Glen Elendra Archmage", 94, Rarity.RARE, mage.cards.g.GlenElendraArchmage.class));
|
||||
cards.add(new SetCardInfo("Glen Elendra Liege", 138, Rarity.RARE, mage.cards.g.GlenElendraLiege.class));
|
||||
cards.add(new SetCardInfo("Gylwain, Casting Director", 4, Rarity.MYTHIC, mage.cards.g.GylwainCastingDirector.class));
|
||||
cards.add(new SetCardInfo("Gylwain, Casting Director", 4, Rarity.MYTHIC, mage.cards.g.GylwainCastingDirector.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Gylwain, Casting Director", 37, Rarity.MYTHIC, mage.cards.g.GylwainCastingDirector.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Hall of Heliod's Generosity", 162, Rarity.RARE, mage.cards.h.HallOfHeliodsGenerosity.class));
|
||||
cards.add(new SetCardInfo("Halo Forager", 139, Rarity.UNCOMMON, mage.cards.h.HaloForager.class));
|
||||
cards.add(new SetCardInfo("Hullbreaker Horror", 95, Rarity.RARE, mage.cards.h.HullbreakerHorror.class));
|
||||
|
|
@ -85,25 +99,33 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Keep Watch", 98, Rarity.COMMON, mage.cards.k.KeepWatch.class));
|
||||
cards.add(new SetCardInfo("Kenrith's Transformation", 128, Rarity.UNCOMMON, mage.cards.k.KenrithsTransformation.class));
|
||||
cards.add(new SetCardInfo("Kindred Dominance", 113, Rarity.RARE, mage.cards.k.KindredDominance.class));
|
||||
cards.add(new SetCardInfo("Knickknack Ouphe", 18, Rarity.RARE, mage.cards.k.KnickknackOuphe.class));
|
||||
cards.add(new SetCardInfo("Knickknack Ouphe", 18, Rarity.RARE, mage.cards.k.KnickknackOuphe.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Knickknack Ouphe", 54, Rarity.RARE, mage.cards.k.KnickknackOuphe.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Kor Spiritdancer", 69, Rarity.RARE, mage.cards.k.KorSpiritdancer.class));
|
||||
cards.add(new SetCardInfo("Korvold, Gleeful Glutton", 26, Rarity.MYTHIC, mage.cards.k.KorvoldGleefulGlutton.class));
|
||||
cards.add(new SetCardInfo("Korvold, Gleeful Glutton", 26, Rarity.MYTHIC, mage.cards.k.KorvoldGleefulGlutton.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Korvold, Gleeful Glutton", 38, Rarity.MYTHIC, mage.cards.k.KorvoldGleefulGlutton.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Krosan Verge", 163, Rarity.UNCOMMON, mage.cards.k.KrosanVerge.class));
|
||||
cards.add(new SetCardInfo("Liberated Livestock", 5, Rarity.RARE, mage.cards.l.LiberatedLivestock.class));
|
||||
cards.add(new SetCardInfo("Loamcrafter Faun", 19, Rarity.RARE, mage.cards.l.LoamcrafterFaun.class));
|
||||
cards.add(new SetCardInfo("Malleable Impostor", 10, Rarity.RARE, mage.cards.m.MalleableImpostor.class));
|
||||
cards.add(new SetCardInfo("Liberated Livestock", 5, Rarity.RARE, mage.cards.l.LiberatedLivestock.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Liberated Livestock", 41, Rarity.RARE, mage.cards.l.LiberatedLivestock.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Loamcrafter Faun", 19, Rarity.RARE, mage.cards.l.LoamcrafterFaun.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Loamcrafter Faun", 55, Rarity.RARE, mage.cards.l.LoamcrafterFaun.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Malleable Impostor", 10, Rarity.RARE, mage.cards.m.MalleableImpostor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Malleable Impostor", 46, Rarity.RARE, mage.cards.m.MalleableImpostor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Mantle of the Ancients", 70, Rarity.RARE, mage.cards.m.MantleOfTheAncients.class));
|
||||
cards.add(new SetCardInfo("Midnight Clock", 99, Rarity.RARE, mage.cards.m.MidnightClock.class));
|
||||
cards.add(new SetCardInfo("Mind Stone", 148, Rarity.UNCOMMON, mage.cards.m.MindStone.class));
|
||||
cards.add(new SetCardInfo("Misleading Signpost", 11, Rarity.RARE, mage.cards.m.MisleadingSignpost.class));
|
||||
cards.add(new SetCardInfo("Misleading Signpost", 11, Rarity.RARE, mage.cards.m.MisleadingSignpost.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Misleading Signpost", 47, Rarity.RARE, mage.cards.m.MisleadingSignpost.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Myriad Landscape", 164, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class));
|
||||
cards.add(new SetCardInfo("Nettling Nuisance", 15, Rarity.RARE, mage.cards.n.NettlingNuisance.class));
|
||||
cards.add(new SetCardInfo("Nettling Nuisance", 15, Rarity.RARE, mage.cards.n.NettlingNuisance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nettling Nuisance", 51, Rarity.RARE, mage.cards.n.NettlingNuisance.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Nightmare Unmaking", 114, Rarity.RARE, mage.cards.n.NightmareUnmaking.class));
|
||||
cards.add(new SetCardInfo("Nightveil Sprite", 100, Rarity.UNCOMMON, mage.cards.n.NightveilSprite.class));
|
||||
cards.add(new SetCardInfo("Nymris, Oona's Trickster", 141, Rarity.RARE, mage.cards.n.NymrisOonasTrickster.class));
|
||||
cards.add(new SetCardInfo("Oona, Queen of the Fae", 142, Rarity.RARE, mage.cards.o.OonaQueenOfTheFae.class));
|
||||
cards.add(new SetCardInfo("Opt", 101, Rarity.COMMON, mage.cards.o.Opt.class));
|
||||
cards.add(new SetCardInfo("Ox Drover", 6, Rarity.RARE, mage.cards.o.OxDrover.class));
|
||||
cards.add(new SetCardInfo("Ox Drover", 6, Rarity.RARE, mage.cards.o.OxDrover.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Ox Drover", 42, Rarity.RARE, mage.cards.o.OxDrover.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Paradise Druid", 129, Rarity.UNCOMMON, mage.cards.p.ParadiseDruid.class));
|
||||
cards.add(new SetCardInfo("Path of Ancestry", 165, Rarity.COMMON, mage.cards.p.PathOfAncestry.class));
|
||||
cards.add(new SetCardInfo("Perplexing Test", 102, Rarity.RARE, mage.cards.p.PerplexingTest.class));
|
||||
|
|
@ -125,13 +147,15 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Scion of Oona", 109, Rarity.RARE, mage.cards.s.ScionOfOona.class));
|
||||
cards.add(new SetCardInfo("Secluded Glen", 166, Rarity.RARE, mage.cards.s.SecludedGlen.class));
|
||||
cards.add(new SetCardInfo("Setessan Champion", 132, Rarity.RARE, mage.cards.s.SetessanChampion.class));
|
||||
cards.add(new SetCardInfo("Shadow Puppeteers", 12, Rarity.RARE, mage.cards.s.ShadowPuppeteers.class));
|
||||
cards.add(new SetCardInfo("Shadow Puppeteers", 12, Rarity.RARE, mage.cards.s.ShadowPuppeteers.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shadow Puppeteers", 48, Rarity.RARE, mage.cards.s.ShadowPuppeteers.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shalai, Voice of Plenty", 74, Rarity.RARE, mage.cards.s.ShalaiVoiceOfPlenty.class));
|
||||
cards.add(new SetCardInfo("Siona, Captain of the Pyleas", 144, Rarity.UNCOMMON, mage.cards.s.SionaCaptainOfThePyleas.class));
|
||||
cards.add(new SetCardInfo("Snake Umbra", 133, Rarity.UNCOMMON, mage.cards.s.SnakeUmbra.class));
|
||||
cards.add(new SetCardInfo("Snap", 110, Rarity.COMMON, mage.cards.s.Snap.class));
|
||||
cards.add(new SetCardInfo("Sol Ring", 149, Rarity.UNCOMMON, mage.cards.s.SolRing.class));
|
||||
cards.add(new SetCardInfo("Songbirds' Blessing", 7, Rarity.RARE, mage.cards.s.SongbirdsBlessing.class));
|
||||
cards.add(new SetCardInfo("Songbirds' Blessing", 7, Rarity.RARE, mage.cards.s.SongbirdsBlessing.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Songbirds' Blessing", 43, Rarity.RARE, mage.cards.s.SongbirdsBlessing.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Sower of Temptation", 111, Rarity.RARE, mage.cards.s.SowerOfTemptation.class));
|
||||
cards.add(new SetCardInfo("Spectral Steel", 75, Rarity.UNCOMMON, mage.cards.s.SpectralSteel.class));
|
||||
cards.add(new SetCardInfo("Starfield Mystic", 76, Rarity.RARE, mage.cards.s.StarfieldMystic.class));
|
||||
|
|
@ -142,19 +166,26 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Sylvan Ranger", 134, Rarity.COMMON, mage.cards.s.SylvanRanger.class));
|
||||
cards.add(new SetCardInfo("Tainted Isle", 169, Rarity.UNCOMMON, mage.cards.t.TaintedIsle.class));
|
||||
cards.add(new SetCardInfo("Talisman of Dominance", 150, Rarity.UNCOMMON, mage.cards.t.TalismanOfDominance.class));
|
||||
cards.add(new SetCardInfo("Tegwyll, Duke of Splendor", 1, Rarity.MYTHIC, mage.cards.t.TegwyllDukeOfSplendor.class));
|
||||
cards.add(new SetCardInfo("Tegwyll, Duke of Splendor", 1, Rarity.MYTHIC, mage.cards.t.TegwyllDukeOfSplendor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tegwyll, Duke of Splendor", 39, Rarity.MYTHIC, mage.cards.t.TegwyllDukeOfSplendor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tegwyll, Duke of Splendor", 58, Rarity.MYTHIC, mage.cards.t.TegwyllDukeOfSplendor.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tegwyll's Scouring", 16, Rarity.RARE, mage.cards.t.TegwyllsScouring.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Tegwyll's Scouring", 52, Rarity.RARE, mage.cards.t.TegwyllsScouring.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Temple of Deceit", 170, Rarity.RARE, mage.cards.t.TempleOfDeceit.class));
|
||||
cards.add(new SetCardInfo("Temple of Plenty", 171, Rarity.RARE, mage.cards.t.TempleOfPlenty.class));
|
||||
cards.add(new SetCardInfo("Temple of the False God", 172, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class));
|
||||
cards.add(new SetCardInfo("Theoretical Duplication", 112, Rarity.RARE, mage.cards.t.TheoreticalDuplication.class));
|
||||
cards.add(new SetCardInfo("Thrilling Encore", 118, Rarity.RARE, mage.cards.t.ThrillingEncore.class));
|
||||
cards.add(new SetCardInfo("Throne of Eldraine", 28, Rarity.RARE, mage.cards.t.ThroneOfEldraine.class));
|
||||
cards.add(new SetCardInfo("Timber Paladin", 20, Rarity.RARE, mage.cards.t.TimberPaladin.class));
|
||||
cards.add(new SetCardInfo("Throne of Eldraine", 28, Rarity.RARE, mage.cards.t.ThroneOfEldraine.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Throne of Eldraine", 40, Rarity.RARE, mage.cards.t.ThroneOfEldraine.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timber Paladin", 20, Rarity.RARE, mage.cards.t.TimberPaladin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timber Paladin", 56, Rarity.RARE, mage.cards.t.TimberPaladin.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Timely Ward", 79, Rarity.RARE, mage.cards.t.TimelyWard.class));
|
||||
cards.add(new SetCardInfo("Tithe Taker", 80, Rarity.RARE, mage.cards.t.TitheTaker.class));
|
||||
cards.add(new SetCardInfo("Transcendent Envoy", 81, Rarity.COMMON, mage.cards.t.TranscendentEnvoy.class));
|
||||
cards.add(new SetCardInfo("Umbra Mystic", 82, Rarity.RARE, mage.cards.u.UmbraMystic.class));
|
||||
cards.add(new SetCardInfo("Unfinished Business", 8, Rarity.RARE, mage.cards.u.UnfinishedBusiness.class));
|
||||
cards.add(new SetCardInfo("Unfinished Business", 8, Rarity.RARE, mage.cards.u.UnfinishedBusiness.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Unfinished Business", 44, Rarity.RARE, mage.cards.u.UnfinishedBusiness.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Utopia Sprawl", 135, Rarity.COMMON, mage.cards.u.UtopiaSprawl.class));
|
||||
cards.add(new SetCardInfo("Verdant Embrace", 136, Rarity.RARE, mage.cards.v.VerdantEmbrace.class));
|
||||
cards.add(new SetCardInfo("Vitu-Ghazi, the City-Tree", 173, Rarity.UNCOMMON, mage.cards.v.VituGhaziTheCityTree.class));
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
* @author LevelX2, JayDi85
|
||||
*/
|
||||
public class CopySpellTest extends CardTestPlayerBase {
|
||||
|
||||
|
|
@ -905,4 +905,56 @@ public class CopySpellTest extends CardTestPlayerBase {
|
|||
Assert.fail(infoPrefix + " - " + "cards must have same zone and zcc: " + zcc1 + " - " + zone1 + " != " + zcc2 + " - " + zone2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug: If Swan Song is used to counter a copied spell, no tokens are created #12883
|
||||
*/
|
||||
@Test
|
||||
public void test_LKI() {
|
||||
// Counter target enchantment, instant, or sorcery spell.
|
||||
// Its controller creates a 2/2 blue Bird creature token with flying.
|
||||
addCard(Zone.HAND, playerA, "Swan Song", 1); // {U}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
//
|
||||
// Until end of turn, whenever a player casts an instant or sorcery spell, that player copies it and
|
||||
// may choose new targets for the copy.
|
||||
addCard(Zone.HAND, playerA, "Bonus Round", 1); // {1}{R}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
//
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // {R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Augmenting Automaton", 1);
|
||||
|
||||
checkPermanentCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerA, "Bird Token", 0);
|
||||
checkPermanentCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Grizzly Bears", 1);
|
||||
checkPermanentCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Augmenting Automaton", 1);
|
||||
|
||||
// prepare copy effect
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 3);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bonus Round");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// cast and duplicate bolt
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt");
|
||||
addTarget(playerA, "Grizzly Bears"); // original target
|
||||
setChoice(playerA, true); // use new target
|
||||
addTarget(playerA, "Augmenting Automaton"); // copy target
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true); // resolve copy trigger
|
||||
checkStackObject("on copy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", 2);
|
||||
|
||||
// counter copy and save Augmenting Automaton
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swan Song", "Lightning Bolt[only copy]", "Lightning Bolt", StackClause.WHILE_COPY_ON_STACK);
|
||||
setChoice(playerA, false); // no change target for duplicated counter spell (non-relevant here)
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerA, "Bird Token", 1);
|
||||
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Grizzly Bears", 0);
|
||||
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Augmenting Automaton", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package org.mage.test.cards.replacement.prevent;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class TheMindskinnerTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String mindskinner = "The Mindskinner"; // 10/1 can't be blocked
|
||||
// If a source you control would deal damage to an opponent, prevent that damage and each opponent mills that many cards.
|
||||
|
||||
private static final String piker = "Goblin Piker"; // 2/1
|
||||
|
||||
private static final String bolt = "Lightning Bolt";
|
||||
|
||||
@Test
|
||||
public void testPreventionAndMill() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, mindskinner);
|
||||
addCard(Zone.BATTLEFIELD, playerA, piker);
|
||||
addCard(Zone.HAND, playerA, bolt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB);
|
||||
|
||||
attack(1, playerA, piker, playerB);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
assertGraveyardCount(playerA, 1); // bolt
|
||||
assertGraveyardCount(playerB, 5);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1291,7 +1291,7 @@ public class TestPlayer implements Player {
|
|||
private void printStack(Game game) {
|
||||
System.out.println("Stack objects: " + game.getStack().size());
|
||||
game.getStack().forEach(stack -> {
|
||||
System.out.println(stack.getStackAbility().toString());
|
||||
System.out.println(stack.getStackAbility().toString() + (stack.isCopy() ? " [copy]" : ""));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -514,8 +514,9 @@ public class BoosterGenerationTest extends MageTestPlayerBase {
|
|||
@Ignore // debug only: collect info about cards in boosters, see https://github.com/magefree/mage/issues/8081
|
||||
@Test
|
||||
public void test_CollectBoosterStats() {
|
||||
ExpansionSet setToAnalyse = ModernHorizons3.getInstance();
|
||||
int openBoosters = 10000;
|
||||
ExpansionSet setToAnalyse = NewPhyrexia.getInstance();
|
||||
// Takes about a minute for 100,000 boosters
|
||||
int openBoosters = 100000;
|
||||
|
||||
Map<String, Integer> resRatio = new HashMap<>();
|
||||
int totalCards = 0;
|
||||
|
|
@ -523,11 +524,23 @@ public class BoosterGenerationTest extends MageTestPlayerBase {
|
|||
List<Card> booster = setToAnalyse.createBooster();
|
||||
totalCards += booster.size();
|
||||
booster.forEach(card -> {
|
||||
String code = String.format("%s %s %s", card.getExpansionSetCode(), card.getRarity().getCode(), card.getName());
|
||||
String code = String.format("%s %s %s", card.getExpansionSetCode(), card.getRarity().toString().charAt(0), card.getName());
|
||||
resRatio.putIfAbsent(code, 0);
|
||||
resRatio.computeIfPresent(code, (u, count) -> count + 1);
|
||||
});
|
||||
}
|
||||
System.out.println(setToAnalyse.getName() + " - boosters opened: " + openBoosters + ". Found cards: " + totalCards + "\n");
|
||||
for (char rarity : Arrays.asList('C', 'U', 'R', 'M', 'S', 'L', 'B')) {
|
||||
List<Integer> rarityCounts = resRatio.entrySet().stream()
|
||||
.filter(e -> e.getKey().charAt(4) == rarity)
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toList());
|
||||
if (!rarityCounts.isEmpty()) {
|
||||
System.out.println(rarity + String.format(": %s unique, min %s, max %s, total %s",
|
||||
rarityCounts.size(), Collections.min(rarityCounts), Collections.max(rarityCounts),
|
||||
rarityCounts.stream().mapToInt(x -> x).sum()));
|
||||
}
|
||||
}
|
||||
List<String> info = resRatio.entrySet().stream()
|
||||
.sorted((o1, o2) -> Integer.compare(o2.getValue(), o1.getValue()))
|
||||
.map(e -> String.format("%s: %d",
|
||||
|
|
@ -535,8 +548,7 @@ public class BoosterGenerationTest extends MageTestPlayerBase {
|
|||
e.getValue()
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
System.out.println(setToAnalyse.getName() + " - boosters opened: " + openBoosters + ". Found cards: " + totalCards + "\n"
|
||||
+ String.join("\n", info));
|
||||
System.out.println("\n" + String.join("\n", info));
|
||||
}
|
||||
|
||||
@Ignore // debug only
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -14,14 +15,21 @@ import mage.util.CardUtil;
|
|||
*/
|
||||
public class PayMoreToCastAsThoughtItHadFlashAbility extends SpellAbility {
|
||||
|
||||
private final ManaCosts costsToAdd;
|
||||
private final Cost costsToAdd;
|
||||
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility(Card card, ManaCosts<ManaCost> costsToAdd) {
|
||||
super(card.getSpellAbility().getManaCosts().copy(), card.getName() + " as though it had flash", Zone.HAND, SpellAbilityType.BASE_ALTERNATE);
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility(Card card, Cost costsToAdd) {
|
||||
super(card.getSpellAbility().getManaCosts().copy(), card.getName(), Zone.HAND, SpellAbilityType.BASE_ALTERNATE);
|
||||
this.costsToAdd = costsToAdd;
|
||||
this.timing = TimingRule.INSTANT;
|
||||
this.setRuleAtTheTop(true);
|
||||
CardUtil.increaseCost(this, costsToAdd);
|
||||
|
||||
if(costsToAdd instanceof ManaCosts<?>) {
|
||||
ManaCosts<ManaCost> manaCosts = (ManaCosts<ManaCost>) costsToAdd;
|
||||
CardUtil.increaseCost(this, manaCosts);
|
||||
}
|
||||
else {
|
||||
this.addCost(costsToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
protected PayMoreToCastAsThoughtItHadFlashAbility(final PayMoreToCastAsThoughtItHadFlashAbility ability) {
|
||||
|
|
@ -38,10 +46,13 @@ public class PayMoreToCastAsThoughtItHadFlashAbility extends SpellAbility {
|
|||
public String getRule(boolean all) {
|
||||
return getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "You may cast {this} as though it had flash if you pay " + costsToAdd.getText() + " more to cast it. <i>(You may cast it any time you could cast an instant.)</i>";
|
||||
if (costsToAdd instanceof ManaCosts) {
|
||||
return "You may cast {this} as though it had flash if you pay " + costsToAdd.getText() + " more to cast it. <i>(You may cast it any time you could cast an instant.)</i>";
|
||||
} else {
|
||||
return "You may cast {this} as though it had flash by " + costsToAdd.getText() + " in addition to paying its other costs.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,8 @@ public class SpellCastAllTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (!filter.match(spell, getControllerId(), this, game)) {
|
||||
if (!filter.match(spell, getControllerId(), this, game)
|
||||
|| !game.getState().getPlayersInRange(getControllerId(), game, false).contains(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
getEffects().setValue("spellCast", spell);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ public interface ContinuousEffect extends Effect {
|
|||
|
||||
boolean isYourNextEndStep(Game game);
|
||||
|
||||
boolean isTheNextEndStep(Game game);
|
||||
|
||||
boolean isYourNextUpkeepStep(Game game);
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -56,9 +56,11 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
|
||||
// until your next turn or until end of your next turn
|
||||
private UUID startingControllerId; // player to check for turn duration (can't different with real controller ability)
|
||||
private UUID activePlayerId; // Player whose turn the effect started on
|
||||
private boolean startingTurnWasActive; // effect started during related players turn and related players turn was already active
|
||||
private int effectStartingOnTurn = 0; // turn the effect started
|
||||
private int effectStartingEndStep = 0;
|
||||
private int effectControllerStartingEndStep = 0;
|
||||
private int effectActivePlayerStartingEndStep = 0;
|
||||
private int nextTurnNumber = Integer.MAX_VALUE; // effect is waiting for a step during your next turn, we store it if found.
|
||||
// set to the turn number on your next turn.
|
||||
private int effectStartingStepNum = 0; // Some continuous are waiting for the next step of a kind.
|
||||
|
|
@ -93,7 +95,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
this.startingControllerId = effect.startingControllerId;
|
||||
this.startingTurnWasActive = effect.startingTurnWasActive;
|
||||
this.effectStartingOnTurn = effect.effectStartingOnTurn;
|
||||
this.effectStartingEndStep = effect.effectStartingEndStep;
|
||||
this.effectControllerStartingEndStep = effect.effectControllerStartingEndStep;
|
||||
this.dependencyTypes = effect.dependencyTypes;
|
||||
this.dependendToTypes = effect.dependendToTypes;
|
||||
this.characterDefining = effect.characterDefining;
|
||||
|
|
@ -251,10 +253,12 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
@Override
|
||||
public void setStartingControllerAndTurnNum(Game game, UUID startingController, UUID activePlayerId) {
|
||||
this.startingControllerId = startingController;
|
||||
this.activePlayerId = activePlayerId;
|
||||
this.startingTurnWasActive = activePlayerId != null
|
||||
&& activePlayerId.equals(startingController); // you can't use "game" for active player cause it's called from tests/cheat too
|
||||
this.effectStartingOnTurn = game.getTurnNum();
|
||||
this.effectStartingEndStep = EndStepCountWatcher.getCount(startingController, game);
|
||||
this.effectControllerStartingEndStep = EndStepCountWatcher.getCount(startingController, game);
|
||||
this.effectActivePlayerStartingEndStep = EndStepCountWatcher.getCount(activePlayerId, game);
|
||||
this.effectStartingStepNum = game.getState().getStepNum();
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +270,12 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
|
||||
@Override
|
||||
public boolean isYourNextEndStep(Game game) {
|
||||
return EndStepCountWatcher.getCount(startingControllerId, game) > effectStartingEndStep;
|
||||
return EndStepCountWatcher.getCount(startingControllerId, game) > effectControllerStartingEndStep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTheNextEndStep(Game game) {
|
||||
return EndStepCountWatcher.getCount(activePlayerId, game) > effectActivePlayerStartingEndStep;
|
||||
}
|
||||
|
||||
public boolean isEndCombatOfYourNextTurn(Game game) {
|
||||
|
|
@ -298,6 +307,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
case UntilYourNextTurn:
|
||||
case UntilEndOfYourNextTurn:
|
||||
case UntilYourNextEndStep:
|
||||
case UntilTheNextEndStep:
|
||||
case UntilEndCombatOfYourNextTurn:
|
||||
case UntilYourNextUpkeepStep:
|
||||
break;
|
||||
|
|
@ -342,6 +352,10 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
return this.isYourNextEndStep(game);
|
||||
}
|
||||
break;
|
||||
case UntilTheNextEndStep:
|
||||
if (player != null && player.isInGame()) {
|
||||
return this.isTheNextEndStep(game);
|
||||
}
|
||||
case UntilEndCombatOfYourNextTurn:
|
||||
if (player != null && player.isInGame()) {
|
||||
return this.isEndCombatOfYourNextTurn(game);
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
case UntilEndOfYourNextTurn:
|
||||
case UntilEndCombatOfYourNextTurn:
|
||||
case UntilYourNextEndStep:
|
||||
case UntilTheNextEndStep:
|
||||
case UntilYourNextUpkeepStep:
|
||||
// until your turn effects continue until real turn reached, their used it's own inactive method
|
||||
// 514.2 Second, the following actions happen simultaneously: all damage marked on permanents
|
||||
|
|
|
|||
|
|
@ -18,21 +18,28 @@ public class IfAbilityHasResolvedXTimesEffect extends OneShotEffect {
|
|||
|
||||
private final int resolutionNumber;
|
||||
private final Effects effects;
|
||||
private final boolean orMore;
|
||||
|
||||
public IfAbilityHasResolvedXTimesEffect(int resolutionNumber, Effect effect) {
|
||||
this(effect.getOutcome(), resolutionNumber, effect);
|
||||
}
|
||||
|
||||
public IfAbilityHasResolvedXTimesEffect(Outcome outcome, int resolutionNumber, Effect... effects) {
|
||||
this(outcome, resolutionNumber, false, effects);
|
||||
}
|
||||
|
||||
public IfAbilityHasResolvedXTimesEffect(Outcome outcome, int resolutionNumber, boolean orMore, Effect... effects) {
|
||||
super(outcome);
|
||||
this.resolutionNumber = resolutionNumber;
|
||||
this.effects = new Effects(effects);
|
||||
this.orMore = orMore;
|
||||
}
|
||||
|
||||
private IfAbilityHasResolvedXTimesEffect(final IfAbilityHasResolvedXTimesEffect effect) {
|
||||
super(effect);
|
||||
this.resolutionNumber = effect.resolutionNumber;
|
||||
this.effects = effect.effects.copy();
|
||||
this.orMore = effect.orMore;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -42,7 +49,8 @@ public class IfAbilityHasResolvedXTimesEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (AbilityResolvedWatcher.getResolutionCount(game, source) != resolutionNumber) {
|
||||
int resolutionCount = AbilityResolvedWatcher.getResolutionCount(game, source);
|
||||
if (resolutionCount < resolutionNumber || (!orMore && resolutionCount > resolutionNumber)) {
|
||||
return false;
|
||||
}
|
||||
boolean result = false;
|
||||
|
|
@ -62,6 +70,9 @@ public class IfAbilityHasResolvedXTimesEffect extends OneShotEffect {
|
|||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
if (orMore) {
|
||||
return "otherwise, " + effects.getText(mode);
|
||||
}
|
||||
return "if this is the " + CardUtil.numberToOrdinalText(resolutionNumber) +
|
||||
" time this ability has resolved this turn, " + effects.getText(mode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ public class EmergeAbility extends SpellAbility {
|
|||
Permanent creature = game.getPermanent(target.getFirstTarget());
|
||||
if (creature != null) {
|
||||
CardUtil.reduceCost(this, creature.getManaValue());
|
||||
if (super.activate(game, allowedIdentifiers, false)) {
|
||||
boolean reducedToZero = this.getManaCostsToPay().isEmpty();
|
||||
if (super.activate(game, allowedIdentifiers, reducedToZero)) {
|
||||
MageObjectReference mor = new MageObjectReference(creature, game);
|
||||
if (creature.sacrifice(this, game)) {
|
||||
this.setCostsTag(EMERGE_ACTIVATION_CREATURE_REFERENCE, mor); //Can access with LKI afterwards
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public class CardNameUtil {
|
|||
.replace("û", "u")
|
||||
.replace("í", "i")
|
||||
.replace("ï", "i")
|
||||
.replace("î", "i")
|
||||
.replace("â", "a")
|
||||
.replace("á", "a")
|
||||
.replace("à", "a")
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public enum TokenRepository {
|
|||
public static final String XMAGE_IMAGE_NAME_NIGHT = "Night";
|
||||
public static final String XMAGE_IMAGE_NAME_THE_MONARCH = "The Monarch";
|
||||
public static final String XMAGE_IMAGE_NAME_RADIATION = "Radiation";
|
||||
public static final String XMAGE_IMAGE_NAME_THE_RING = "The Ring";
|
||||
public static final String XMAGE_IMAGE_NAME_HELPER_EMBLEM = "Helper Emblem";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TokenRepository.class);
|
||||
|
|
@ -306,6 +307,9 @@ public enum TokenRepository {
|
|||
// Radiation (for trigger)
|
||||
res.add(createXmageToken(XMAGE_IMAGE_NAME_RADIATION, 1, "https://api.scryfall.com/cards/tpip/22/en?format=image"));
|
||||
|
||||
// The Ring
|
||||
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_RING, 1, "https://api.scryfall.com/cards/tltr/H13/en?format=image"));
|
||||
|
||||
// Helper emblem (for global card hints)
|
||||
// use backface for it
|
||||
res.add(createXmageToken(XMAGE_IMAGE_NAME_HELPER_EMBLEM, 1, "https://upload.wikimedia.org/wikipedia/en/a/aa/Magic_the_gathering-card_back.jpg"));
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public enum Duration {
|
|||
EndOfTurn("until end of turn", true, true),
|
||||
UntilYourNextTurn("until your next turn", true, true),
|
||||
UntilYourNextEndStep("until your next end step", true, true),
|
||||
UntilTheNextEndStep("until your next end step", true, true),
|
||||
UntilEndCombatOfYourNextTurn("until end of combat on your next turn", true, true),
|
||||
UntilYourNextUpkeepStep("until your next upkeep", true, true),
|
||||
UntilEndOfYourNextTurn("until the end of your next turn", true, true),
|
||||
|
|
|
|||
|
|
@ -583,11 +583,10 @@ public abstract class GameImpl implements Game {
|
|||
if (emblem != null) {
|
||||
return emblem;
|
||||
}
|
||||
|
||||
TheRingEmblem newEmblem = new TheRingEmblem(playerId);
|
||||
|
||||
// TODO: add image info
|
||||
|
||||
state.addCommandObject(newEmblem);
|
||||
|
||||
return newEmblem;
|
||||
}
|
||||
|
||||
|
|
@ -1966,16 +1965,13 @@ public abstract class GameImpl implements Game {
|
|||
@Override
|
||||
public void addEmblem(Emblem emblem, MageObject sourceObject, UUID toPlayerId) {
|
||||
Emblem newEmblem = emblem.copy();
|
||||
newEmblem.setSourceObject(sourceObject);
|
||||
newEmblem.setSourceObjectAndInitImage(sourceObject);
|
||||
newEmblem.setControllerId(toPlayerId);
|
||||
newEmblem.assignNewId();
|
||||
newEmblem.getAbilities().newId();
|
||||
for (Ability ability : newEmblem.getAbilities()) {
|
||||
ability.setSourceId(newEmblem.getId());
|
||||
}
|
||||
|
||||
// image info setup in setSourceObject
|
||||
|
||||
state.addCommandObject(newEmblem);
|
||||
}
|
||||
|
||||
|
|
@ -1997,17 +1993,15 @@ public abstract class GameImpl implements Game {
|
|||
}
|
||||
}
|
||||
Plane newPlane = plane.copy();
|
||||
newPlane.setSourceObject();
|
||||
newPlane.setSourceObjectAndInitImage();
|
||||
newPlane.setControllerId(toPlayerId);
|
||||
newPlane.assignNewId();
|
||||
newPlane.getAbilities().newId();
|
||||
for (Ability ability : newPlane.getAbilities()) {
|
||||
ability.setSourceId(newPlane.getId());
|
||||
}
|
||||
|
||||
// image info setup in setSourceObject
|
||||
|
||||
state.addCommandObject(newPlane);
|
||||
|
||||
informPlayers("You have planeswalked to " + newPlane.getLogName());
|
||||
|
||||
// Fire off the planeswalked event
|
||||
|
|
@ -2028,7 +2022,6 @@ public abstract class GameImpl implements Game {
|
|||
@Override
|
||||
public Dungeon addDungeon(Dungeon dungeon, UUID playerId) {
|
||||
dungeon.setControllerId(playerId);
|
||||
dungeon.setSourceObject();
|
||||
state.addCommandObject(dungeon);
|
||||
return dungeon;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1239,6 +1239,11 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.isPlaneChase = isPlaneChase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add object to command zone.
|
||||
* <p>
|
||||
* Warning, all object data must be initialized before adding, including image info
|
||||
*/
|
||||
public void addCommandObject(CommandObject commandObject) {
|
||||
getCommand().add(commandObject);
|
||||
setZone(commandObject.getId(), Zone.COMMAND);
|
||||
|
|
|
|||
|
|
@ -154,24 +154,35 @@ public class Dungeon extends CommandObjectImpl {
|
|||
}
|
||||
|
||||
public static Dungeon createDungeon(String name, boolean isNameMustExists) {
|
||||
Dungeon res;
|
||||
switch (name) {
|
||||
case "Tomb of Annihilation":
|
||||
return new TombOfAnnihilationDungeon();
|
||||
res = new TombOfAnnihilationDungeon();
|
||||
break;
|
||||
case "Lost Mine of Phandelver":
|
||||
return new LostMineOfPhandelverDungeon();
|
||||
res = new LostMineOfPhandelverDungeon();
|
||||
break;
|
||||
case "Dungeon of the Mad Mage":
|
||||
return new DungeonOfTheMadMageDungeon();
|
||||
res = new DungeonOfTheMadMageDungeon();
|
||||
break;
|
||||
default:
|
||||
if (isNameMustExists) {
|
||||
throw new UnsupportedOperationException("A dungeon should have been chosen");
|
||||
} else {
|
||||
return null;
|
||||
res = null;
|
||||
}
|
||||
}
|
||||
|
||||
// dungeon don't have source, so image data can be initialized immediately
|
||||
if (res != null) {
|
||||
res.setSourceObjectAndInitImage();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void setSourceObject() {
|
||||
// choose set code due source
|
||||
public void setSourceObjectAndInitImage() {
|
||||
// image
|
||||
TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForClass(this.getClass().getName(), null);
|
||||
if (foundInfo != null) {
|
||||
this.setExpansionSetCode(foundInfo.getSetCode());
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public abstract class Emblem extends CommandObjectImpl {
|
|||
return frameStyle;
|
||||
}
|
||||
|
||||
public void setSourceObject(MageObject sourceObject) {
|
||||
public void setSourceObjectAndInitImage(MageObject sourceObject) {
|
||||
this.sourceObject = sourceObject;
|
||||
|
||||
// choose set code due source
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public abstract class Plane extends CommandObjectImpl {
|
|||
return frameStyle;
|
||||
}
|
||||
|
||||
public void setSourceObject() {
|
||||
public void setSourceObjectAndInitImage() {
|
||||
this.sourceObject = null;
|
||||
|
||||
// choose set code due source
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public final class EmblemOfCard extends Emblem {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setSourceObject(MageObject sourceObject) {
|
||||
public void setSourceObjectAndInitImage(MageObject sourceObject) {
|
||||
this.sourceObject = sourceObject;
|
||||
// super method would try and fail to find the emblem image here
|
||||
// (not sure why that would be setSoureObject's job; we get our image during construction)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class RadiationEmblem extends Emblem {
|
|||
this.setImageFileName(""); // use default
|
||||
this.setImageNumber(foundInfo.getImageNumber());
|
||||
} else {
|
||||
// how-to fix: add emblem to the tokens-database TokenRepository->loadXmageTokens
|
||||
// how-to fix: add image to the tokens-database TokenRepository->loadXmageTokens
|
||||
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_RADIATION);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
|||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||
import mage.abilities.effects.common.SacrificeTargetEffect;
|
||||
import mage.cards.repository.TokenInfo;
|
||||
import mage.cards.repository.TokenRepository;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
|
|
@ -41,6 +43,19 @@ public final class TheRingEmblem extends Emblem {
|
|||
public TheRingEmblem(UUID controllerId) {
|
||||
super("The Ring");
|
||||
this.setControllerId(controllerId);
|
||||
|
||||
// ring don't have source, so image can be initialized immediately
|
||||
TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForXmage(TokenRepository.XMAGE_IMAGE_NAME_THE_RING, null);
|
||||
if (foundInfo != null) {
|
||||
this.setExpansionSetCode(foundInfo.getSetCode());
|
||||
this.setUsesVariousArt(false);
|
||||
this.setCardNumber("");
|
||||
this.setImageFileName(""); // use default
|
||||
this.setImageNumber(foundInfo.getImageNumber());
|
||||
} else {
|
||||
// how-to fix: add image to the tokens-database TokenRepository->loadXmageTokens
|
||||
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_THE_RING);
|
||||
}
|
||||
}
|
||||
|
||||
private TheRingEmblem(final TheRingEmblem card) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public class XmageHelperEmblem extends Emblem {
|
|||
this.setImageFileName(""); // use default
|
||||
this.setImageNumber(foundInfo.getImageNumber());
|
||||
} else {
|
||||
// how-to fix: add emblem to the tokens-database TokenRepository->loadXmageTokens
|
||||
// how-to fix: add image to the tokens-database TokenRepository->loadXmageTokens
|
||||
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_HELPER_EMBLEM);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,9 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
counteredObjectName = "Ability (" + stackObject.getStackAbility().getRule(targetSourceName) + ") of " + targetSourceName;
|
||||
}
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, source, stackObject.getControllerId()))) {
|
||||
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement
|
||||
// spells are removed from stack by the card movement
|
||||
if (!(stackObject instanceof Spell)
|
||||
|| stackObject.isCopy()) { // !ensure that copies of stackobjects have their history recorded ie: Swan Song
|
||||
this.remove(stackObject, game);
|
||||
game.rememberLKI(Zone.STACK, stackObject);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1035,6 +1035,7 @@ public final class CardUtil {
|
|||
|| text.startsWith("any ")
|
||||
|| text.startsWith("{this} ")
|
||||
|| text.startsWith("your ")
|
||||
|| text.startsWith("their ")
|
||||
|| text.startsWith("one ")) {
|
||||
return text;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue