diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 6d900146e40..f6748d91506 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -55,6 +55,16 @@ public final class Main { private static final Logger logger = Logger.getLogger(Main.class); private static final MageVersion version = new MageVersion(Main.class); + // Server threads: + // - worker threads: creates for each connection, controls by maxPoolSize; + // - acceptor threads: processing requests to start a new connection, controls by numAcceptThreads; + // - backlog threads: processing waiting queue if maxPoolSize reached, controls by backlogSize; + // Usage hints: + // - if maxPoolSize reached then new clients will freeze in connection dialog until backlog queue overflow; + // - so for active server must increase maxPoolSize to big value like "max online * 10" or enable worker idle timeout + // - worker idle time will free unused worker thread, so new client can connect; + private static final int SERVER_WORKER_THREAD_IDLE_TIMEOUT_SECS = 5 * 60; // no needs to config, must be enabled for all + // arg settings can be setup by run script or IDE's program arguments like -xxx=yyy // prop settings can be setup by -Dxxx=yyy in the launcher // priority: default setting -> prop setting -> arg setting @@ -432,6 +442,7 @@ public final class Main { ((BisocketServerInvoker) invoker).setSecondaryBindPort(managerFactory.configSettings().getSecondaryBindPort()); ((BisocketServerInvoker) invoker).setBacklog(managerFactory.configSettings().getBacklogSize()); ((BisocketServerInvoker) invoker).setNumAcceptThreads(managerFactory.configSettings().getNumAcceptThreads()); + ((BisocketServerInvoker) invoker).setIdleTimeout(SERVER_WORKER_THREAD_IDLE_TIMEOUT_SECS); } @Override diff --git a/Mage.Sets/src/mage/cards/b/BountyBoard.java b/Mage.Sets/src/mage/cards/b/BountyBoard.java new file mode 100644 index 00000000000..1f8157c9edc --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BountyBoard.java @@ -0,0 +1,101 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; + +/** + * @author TheElk801 + */ +public final class BountyBoard extends CardImpl { + + private static final FilterPermanent filter + = new FilterCreaturePermanent("a creature with a bounty counter on it"); + + static { + filter.add(CounterType.BOUNTY.getPredicate()); + } + + public BountyBoard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + + // {1}, {T}: Put a bounty counter on target creature. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), new GenericManaCost(1) + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // Whenever a creature with a bounty counter on it dies, each of its controller's opponents draws a card and gains 2 life. + this.addAbility(new DiesCreatureTriggeredAbility(new BountyBoardEffect(), false, filter)); + } + + private BountyBoard(final BountyBoard card) { + super(card); + } + + @Override + public BountyBoard copy() { + return new BountyBoard(this); + } +} + +class BountyBoardEffect extends OneShotEffect { + + BountyBoardEffect() { + super(Outcome.Benefit); + staticText = "each of its controller's opponents draws a card and gains 2 life"; + } + + private BountyBoardEffect(final BountyBoardEffect effect) { + super(effect); + } + + @Override + public BountyBoardEffect copy() { + return new BountyBoardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Optional.ofNullable(getValue("creatureDied")) + .map(Permanent.class::cast) + .map(Controllable::getControllerId) + .map(game::getOpponents) + .map(Collection::stream) + .orElseGet(Stream::empty) + .map(game::getPlayer) + .filter(Objects::nonNull) + .forEach(player -> { + player.drawCards(1, source, game); + player.gainLife(2, game, source); + }); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeadBeforeSunrise.java b/Mage.Sets/src/mage/cards/d/DeadBeforeSunrise.java new file mode 100644 index 00000000000..aa1f58a12de --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeadBeforeSunrise.java @@ -0,0 +1,54 @@ +package mage.cards.d; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DamageWithPowerFromSourceToAnotherTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.OutlawPredicate; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DeadBeforeSunrise extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(OutlawPredicate.instance); + } + + public DeadBeforeSunrise(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}"); + + // Until end of turn, outlaw creatures you control get +1/+0 and gain "{T}: This creature deals damage equal to its power to target creature." + this.getSpellAbility().addEffect(new BoostControlledEffect( + 1, 0, Duration.EndOfTurn, filter + ).setText("until end of turn, outlaw creatures you control get +1/+0")); + Ability ability = new SimpleActivatedAbility( + new DamageWithPowerFromSourceToAnotherTargetEffect("this creature"), new TapSourceCost() + ); + ability.addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new GainAbilityControlledEffect( + ability, Duration.EndOfTurn, filter + ).setText("and gain \"{T}: This creature deals damage equal to its power to target creature.\"")); + } + + private DeadBeforeSunrise(final DeadBeforeSunrise card) { + super(card); + } + + @Override + public DeadBeforeSunrise copy() { + return new DeadBeforeSunrise(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GraywatersFixer.java b/Mage.Sets/src/mage/cards/g/GraywatersFixer.java new file mode 100644 index 00000000000..c1b1a7818a5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GraywatersFixer.java @@ -0,0 +1,77 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.keyword.UnearthAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GraywatersFixer extends CardImpl { + + public GraywatersFixer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}"); + + this.subtype.add(SubType.LIZARD); + this.subtype.add(SubType.MERCENARY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Each outlaw creature card in your graveyard has encore {X}, where X is its mana value. + this.addAbility(new SimpleStaticAbility(new GraywatersFixerEffect())); + } + + private GraywatersFixer(final GraywatersFixer card) { + super(card); + } + + @Override + public GraywatersFixer copy() { + return new GraywatersFixer(this); + } +} + +class GraywatersFixerEffect extends ContinuousEffectImpl { + GraywatersFixerEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + staticText = "each outlaw creature card in your graveyard has encore {X}, where X is its mana value"; + } + + private GraywatersFixerEffect(final GraywatersFixerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + for (Card card : controller.getGraveyard().getCards(game)) { + if (!card.isCreature(game) || !card.isOutlaw(game)) { + continue; + } + UnearthAbility ability = new UnearthAbility(new GenericManaCost(card.getManaValue())); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + return true; + } + + @Override + public GraywatersFixerEffect copy() { + return new GraywatersFixerEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PreWarFormalwear.java b/Mage.Sets/src/mage/cards/p/PreWarFormalwear.java new file mode 100644 index 00000000000..5728316de79 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PreWarFormalwear.java @@ -0,0 +1,102 @@ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class PreWarFormalwear extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature card with mana value 3 or less from your graveyard"); + + static { + filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3)); + filter.add(CardType.CREATURE.getPredicate()); + } + + public PreWarFormalwear(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{W}"); + + this.subtype.add(SubType.EQUIPMENT); + + // When Pre-War Formalwear enters the battlefield, return target creature card with mana value 3 or less from your graveyard to the battlefield and attach Pre-War Formalwear to it. + Ability ability = new EntersBattlefieldTriggeredAbility(new PreWarFormalwerEffect()); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); + + // Equipped creature gets +2/+2 and has vigilance. + ability = new SimpleStaticAbility(new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield)); + ability.addEffect(new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA).setText("and has vigilance")); + this.addAbility(ability); + + // Equip {3} + this.addAbility(new EquipAbility(3)); + } + + private PreWarFormalwear(final PreWarFormalwear card) { + super(card); + } + + @Override + public PreWarFormalwear copy() { + return new PreWarFormalwear(this); + } +} + +class PreWarFormalwerEffect extends OneShotEffect { + + PreWarFormalwerEffect() { + super(Outcome.PutCreatureInPlay); + staticText = "return target creature card with mana value 3 or less from your graveyard " + + "to the battlefield and attach Pre-War Formalwear to it"; + } + + private PreWarFormalwerEffect(final PreWarFormalwerEffect effect) { + super(effect); + } + + @Override + public PreWarFormalwerEffect copy() { + return new PreWarFormalwerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(source.getFirstTarget()); + Player player = game.getPlayer(source.getControllerId()); + if (card == null || player == null) { + return false; + } + player.moveCards(card, Zone.BATTLEFIELD, source, game); + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + new AttachEffect(Outcome.BoostCreature) + .setTargetPointer(new FixedTarget(permanent.getId())) + .apply(game, source); + } + return true; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PyreticCharge.java b/Mage.Sets/src/mage/cards/p/PyreticCharge.java new file mode 100644 index 00000000000..c99a3f5480a --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PyreticCharge.java @@ -0,0 +1,71 @@ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.PlotAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PyreticCharge extends CardImpl { + + public PyreticCharge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}"); + + // Discard your hand, then draw four cards. For each card discarded this way, creatures you control get +1/+0 until end of turn. + this.getSpellAbility().addEffect(new PyreticChargeEffect()); + + // Plot {3}{R} + this.addAbility(new PlotAbility("{3}{R}")); + } + + private PyreticCharge(final PyreticCharge card) { + super(card); + } + + @Override + public PyreticCharge copy() { + return new PyreticCharge(this); + } +} + +class PyreticChargeEffect extends OneShotEffect { + + PyreticChargeEffect() { + super(Outcome.Benefit); + staticText = "discard your hand, then draw four cards. For each card discarded this way, " + + "creatures you control get +1/+0 until end of turn"; + } + + private PyreticChargeEffect(final PyreticChargeEffect effect) { + super(effect); + } + + @Override + public PyreticChargeEffect copy() { + return new PyreticChargeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + int count = player.getHand().size(); + player.discard(count, false, false, source, game); + player.drawCards(4, source, game); + game.addEffect(new BoostControlledEffect(count, 0, Duration.EndOfTurn), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SigardasVanguard.java b/Mage.Sets/src/mage/cards/s/SigardasVanguard.java index 78db6bae4df..72506bb5e56 100644 --- a/Mage.Sets/src/mage/cards/s/SigardasVanguard.java +++ b/Mage.Sets/src/mage/cards/s/SigardasVanguard.java @@ -80,6 +80,7 @@ class SigardasVanguardEffect extends OneShotEffect { return false; } TargetPermanent target = new TargetCreaturesWithDifferentPowers(); + target.withNotTarget(true); player.choose(outcome, target, source, game); if (target.getTargets().isEmpty()) { return false; diff --git a/Mage.Sets/src/mage/cards/t/ThievingVarmint.java b/Mage.Sets/src/mage/cards/t/ThievingVarmint.java new file mode 100644 index 00000000000..130e262f443 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThievingVarmint.java @@ -0,0 +1,61 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.mana.ConditionalAnyColorManaAbility; +import mage.abilities.mana.conditional.ConditionalSpellManaBuilder; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ThievingVarmint extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("spells you don't own"); + + static { + filter.add(TargetController.NOT_YOU.getOwnerPredicate()); + } + + public ThievingVarmint(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.VARMINT); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // {T}, Pay 1 life: Add two mana of any one color. Spend this mana only to cast spells you don't own. + Ability ability = new ConditionalAnyColorManaAbility( + new TapSourceCost(), 2, + new ConditionalSpellManaBuilder(filter), true + ); + ability.addCost(new PayLifeCost(1)); + this.addAbility(ability); + } + + private ThievingVarmint(final ThievingVarmint card) { + super(card); + } + + @Override + public ThievingVarmint copy() { + return new ThievingVarmint(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TowerWinder.java b/Mage.Sets/src/mage/cards/t/TowerWinder.java new file mode 100644 index 00000000000..c9473d3b192 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TowerWinder.java @@ -0,0 +1,53 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TowerWinder extends CardImpl { + + private static final FilterCard filter = new FilterCard("Command Tower"); + + static { + filter.add(new NamePredicate("Command Tower")); + } + + public TowerWinder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.SNAKE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // When Tower Winder enters the battlefield, search your library and/or graveyard for a card named Command Tower, reveal it, and put it into your hand. If you search your library this way, shuffle. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryGraveyardPutInHandEffect(filter))); + } + + private TowerWinder(final TowerWinder card) { + super(card); + } + + @Override + public TowerWinder copy() { + return new TowerWinder(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Fallout.java b/Mage.Sets/src/mage/sets/Fallout.java index a1d9e23bef4..dc89802155c 100644 --- a/Mage.Sets/src/mage/sets/Fallout.java +++ b/Mage.Sets/src/mage/sets/Fallout.java @@ -220,6 +220,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Plains", 317, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Powder Ganger", 65, Rarity.RARE, mage.cards.p.PowderGanger.class)); cards.add(new SetCardInfo("Prairie Stream", 280, Rarity.RARE, mage.cards.p.PrairieStream.class)); + cards.add(new SetCardInfo("Pre-War Formalwear", 21, Rarity.RARE, mage.cards.p.PreWarFormalwear.class)); cards.add(new SetCardInfo("Puresteel Paladin", 170, Rarity.RARE, mage.cards.p.PuresteelPaladin.class)); cards.add(new SetCardInfo("Putrefy", 219, Rarity.UNCOMMON, mage.cards.p.Putrefy.class)); cards.add(new SetCardInfo("Radstorm", 37, Rarity.RARE, mage.cards.r.Radstorm.class)); diff --git a/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java b/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java index 93f9802a138..2e20f983ccb 100644 --- a/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java +++ b/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java @@ -46,6 +46,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet { cards.add(new SetCardInfo("Bojuka Bog", 273, Rarity.COMMON, mage.cards.b.BojukaBog.class)); cards.add(new SetCardInfo("Bonders' Enclave", 274, Rarity.RARE, mage.cards.b.BondersEnclave.class)); cards.add(new SetCardInfo("Boros Charm", 216, Rarity.UNCOMMON, mage.cards.b.BorosCharm.class)); + cards.add(new SetCardInfo("Bounty Board", 37, Rarity.RARE, mage.cards.b.BountyBoard.class)); cards.add(new SetCardInfo("Brainstealer Dragon", 127, Rarity.RARE, mage.cards.b.BrainstealerDragon.class)); cards.add(new SetCardInfo("Breena, the Demagogue", 217, Rarity.MYTHIC, mage.cards.b.BreenaTheDemagogue.class)); cards.add(new SetCardInfo("Cactus Preserve", 40, Rarity.RARE, mage.cards.c.CactusPreserve.class)); @@ -77,6 +78,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet { cards.add(new SetCardInfo("Darksteel Ingot", 256, Rarity.UNCOMMON, mage.cards.d.DarksteelIngot.class)); cards.add(new SetCardInfo("Darkwater Catacombs", 282, Rarity.RARE, mage.cards.d.DarkwaterCatacombs.class)); cards.add(new SetCardInfo("Dazzling Sphinx", 93, Rarity.RARE, mage.cards.d.DazzlingSphinx.class)); + cards.add(new SetCardInfo("Dead Before Sunrise", 26, Rarity.RARE, mage.cards.d.DeadBeforeSunrise.class)); cards.add(new SetCardInfo("Deadly Dispute", 131, Rarity.COMMON, mage.cards.d.DeadlyDispute.class)); cards.add(new SetCardInfo("Decimate", 220, Rarity.RARE, mage.cards.d.Decimate.class)); cards.add(new SetCardInfo("Deep Analysis", 94, Rarity.COMMON, mage.cards.d.DeepAnalysis.class)); @@ -128,6 +130,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet { cards.add(new SetCardInfo("Glittering Stockpile", 167, Rarity.UNCOMMON, mage.cards.g.GlitteringStockpile.class)); cards.add(new SetCardInfo("Goblin Electromancer", 228, Rarity.COMMON, mage.cards.g.GoblinElectromancer.class)); cards.add(new SetCardInfo("Gonti, Lord of Luxury", 135, Rarity.RARE, mage.cards.g.GontiLordOfLuxury.class)); + cards.add(new SetCardInfo("Graywater's Fixer", 36, Rarity.RARE, mage.cards.g.GraywatersFixer.class)); cards.add(new SetCardInfo("Grenzo, Havoc Raiser", 168, Rarity.RARE, mage.cards.g.GrenzoHavocRaiser.class)); cards.add(new SetCardInfo("Guttersnipe", 169, Rarity.COMMON, mage.cards.g.Guttersnipe.class)); cards.add(new SetCardInfo("Harrow", 194, Rarity.COMMON, mage.cards.h.Harrow.class)); @@ -203,6 +206,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet { cards.add(new SetCardInfo("Propaganda", 108, Rarity.UNCOMMON, mage.cards.p.Propaganda.class)); cards.add(new SetCardInfo("Pteramander", 109, Rarity.UNCOMMON, mage.cards.p.Pteramander.class)); cards.add(new SetCardInfo("Putrefy", 238, Rarity.UNCOMMON, mage.cards.p.Putrefy.class)); + cards.add(new SetCardInfo("Pyretic Charge", 29, Rarity.RARE, mage.cards.p.PyreticCharge.class)); cards.add(new SetCardInfo("Queen Marchesa", 239, Rarity.RARE, mage.cards.q.QueenMarchesa.class)); cards.add(new SetCardInfo("Radical Idea", 110, Rarity.COMMON, mage.cards.r.RadicalIdea.class)); cards.add(new SetCardInfo("Rain of Riches", 177, Rarity.RARE, mage.cards.r.RainOfRiches.class)); @@ -272,11 +276,13 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet { cards.add(new SetCardInfo("Thief of Sanity", 243, Rarity.RARE, mage.cards.t.ThiefOfSanity.class)); cards.add(new SetCardInfo("Thieving Amalgam", 150, Rarity.RARE, mage.cards.t.ThievingAmalgam.class)); cards.add(new SetCardInfo("Thieving Skydiver", 118, Rarity.RARE, mage.cards.t.ThievingSkydiver.class)); + cards.add(new SetCardInfo("Thieving Varmint", 23, Rarity.RARE, mage.cards.t.ThievingVarmint.class)); cards.add(new SetCardInfo("Think Twice", 119, Rarity.COMMON, mage.cards.t.ThinkTwice.class)); cards.add(new SetCardInfo("Third Path Iconoclast", 244, Rarity.UNCOMMON, mage.cards.t.ThirdPathIconoclast.class)); cards.add(new SetCardInfo("Three Visits", 209, Rarity.UNCOMMON, mage.cards.t.ThreeVisits.class)); cards.add(new SetCardInfo("Thrilling Discovery", 245, Rarity.COMMON, mage.cards.t.ThrillingDiscovery.class)); cards.add(new SetCardInfo("Titania, Protector of Argoth", 210, Rarity.MYTHIC, mage.cards.t.TitaniaProtectorOfArgoth.class)); + cards.add(new SetCardInfo("Tower Winder", 34, Rarity.RARE, mage.cards.t.TowerWinder.class)); cards.add(new SetCardInfo("Trailblazer's Boots", 269, Rarity.UNCOMMON, mage.cards.t.TrailblazersBoots.class)); cards.add(new SetCardInfo("Treasure Cruise", 120, Rarity.COMMON, mage.cards.t.TreasureCruise.class)); cards.add(new SetCardInfo("Triton Shorestalker", 121, Rarity.COMMON, mage.cards.t.TritonShorestalker.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/UnearthAbility.java b/Mage/src/main/java/mage/abilities/keyword/UnearthAbility.java index a924b3db748..dc669636304 100644 --- a/Mage/src/main/java/mage/abilities/keyword/UnearthAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/UnearthAbility.java @@ -3,7 +3,7 @@ package mage.abilities.keyword; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.costs.Cost; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileSourceEffect; @@ -14,7 +14,6 @@ import mage.constants.TimingRule; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; /** @@ -32,7 +31,7 @@ import mage.game.events.ZoneChangeEvent; */ public class UnearthAbility extends ActivatedAbilityImpl { - public UnearthAbility(ManaCosts costs) { + public UnearthAbility(Cost costs) { super(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false, true, true), costs); this.timing = TimingRule.SORCERY; this.addEffect(new CreateDelayedTriggeredAbilityEffect(new UnearthDelayedTriggeredAbility()));