From 7f4d9087aa02196bc7311873e104c0e6ac178506 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 13:30:33 +0000 Subject: [PATCH 01/71] Implemented Azor, the Lawbringer --- .../src/mage/cards/a/AzorTheLawbringer.java | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java diff --git a/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java b/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java new file mode 100644 index 00000000000..6216709a868 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AzorTheLawbringer.java @@ -0,0 +1,209 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 & L_J + */ +public class AzorTheLawbringer extends CardImpl { + + public AzorTheLawbringer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{W}{U}{U}"); + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Azor, the Lawbringer enters the battlefield, each opponent can’t cast instant or sorcery spells during that player’s next turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new AzorTheLawbringerEntersBattlefieldEffect(), false)); + + // Whenever Azor attacks, you may pay {X}{W}{U}{U}. If you do, you gain X life and draw X cards. + this.addAbility(new AttacksTriggeredAbility(new AzorTheLawbringerAttacksEffect(), false)); + } + + public AzorTheLawbringer(final AzorTheLawbringer card) { + super(card); + } + + @Override + public AzorTheLawbringer copy() { + return new AzorTheLawbringer(this); + } +} + +class AzorTheLawbringerEntersBattlefieldEffect extends OneShotEffect { + + public AzorTheLawbringerEntersBattlefieldEffect() { + super(Outcome.Benefit); + this.staticText = "each opponent can't cast instant or sorcery spells during that player's next turn"; + } + + public AzorTheLawbringerEntersBattlefieldEffect(final AzorTheLawbringerEntersBattlefieldEffect effect) { + super(effect); + } + + @Override + public AzorTheLawbringerEntersBattlefieldEffect copy() { + return new AzorTheLawbringerEntersBattlefieldEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + ContinuousEffect effect = new AzorTheLawbringerCantCastEffect(); + effect.setTargetPointer(new FixedTarget(opponentId)); + game.addEffect(effect, source); + } + return true; + } +} + +class AzorTheLawbringerCantCastEffect extends ContinuousRuleModifyingEffectImpl { + + int playersNextTurn; + + public AzorTheLawbringerCantCastEffect() { + super(Duration.Custom, Outcome.Detriment); + staticText = "You can't cast instant or sorcery spells during this turn"; + playersNextTurn = 0; + } + + public AzorTheLawbringerCantCastEffect(final AzorTheLawbringerCantCastEffect effect) { + super(effect); + this.playersNextTurn = effect.playersNextTurn; + } + + @Override + public AzorTheLawbringerCantCastEffect copy() { + return new AzorTheLawbringerCantCastEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "You can't cast instant or sorcery spells this turn (" + mageObject.getIdName() + ")."; + } + return null; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + UUID opponentId = getTargetPointer().getFirst(game, source); + if (game.getActivePlayerId().equals(opponentId)) { + if (playersNextTurn == 0) { + playersNextTurn = game.getTurnNum(); + } + if (playersNextTurn == game.getTurnNum()) { + if (opponentId.equals(event.getPlayerId())) { + MageObject object = game.getObject(event.getSourceId()); + if (event.getType() == GameEvent.EventType.CAST_SPELL) { + if (object.isInstant() || object.isSorcery()) { + return true; + } + } + } + } else { + discard(); + } + } else if (playersNextTurn > 0) { + discard(); + } + return false; + } +} + +class AzorTheLawbringerAttacksEffect extends OneShotEffect { + + AzorTheLawbringerAttacksEffect() { + super(Outcome.Benefit); + staticText = "you may pay {X}{W}{U}{U}. If you do, you gain X life and draw X cards"; + } + + AzorTheLawbringerAttacksEffect(final AzorTheLawbringerAttacksEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + ManaCosts cost = new ManaCostsImpl("{X}{W}{U}{U}"); + if (controller.chooseUse(Outcome.Damage, "Pay " + cost.getText() + "? If you do, you gain X life and draw X cards.", source, game)) { + int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source); + cost.add(new GenericManaCost(costX)); + if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { + controller.gainLife(costX, game); + controller.drawCards(costX, game); + return true; + } + } + } + return false; + } + + @Override + public AzorTheLawbringerAttacksEffect copy() { + return new AzorTheLawbringerAttacksEffect(this); + } + +} From 275cd904399be36c552279bdd78f72c8a977b6b2 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 13:31:27 +0000 Subject: [PATCH 02/71] Implemented Aquatic Incursion --- .../src/mage/cards/a/AquaticIncursion.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AquaticIncursion.java diff --git a/Mage.Sets/src/mage/cards/a/AquaticIncursion.java b/Mage.Sets/src/mage/cards/a/AquaticIncursion.java new file mode 100644 index 00000000000..ab1c124ce0e --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AquaticIncursion.java @@ -0,0 +1,80 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.permanent.token.MerfolkHexproofToken; +import mage.target.TargetPermanent; + +/** + * + * @author L_J + */ +public class AquaticIncursion extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Merfolk"); + + static { + filter.add(new SubtypePredicate(SubType.MERFOLK)); + } + + public AquaticIncursion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); + + // When Aquatic Incursion enters the battlefield, create two 1/1 blue Merfolk creature tokens with hexproof. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MerfolkHexproofToken(), 2), false)); + + // {3}{U}: Target Merfolk can’t be blocked this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedTargetEffect(Duration.EndOfTurn), new ManaCostsImpl("{3}{U}")); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public AquaticIncursion(final AquaticIncursion card) { + super(card); + } + + @Override + public AquaticIncursion copy() { + return new AquaticIncursion(this); + } +} From 67f964160bce55ba1fcd606703b6462a34c6072a Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 13:32:00 +0000 Subject: [PATCH 03/71] Implemented Brazen Freebooter --- .../src/mage/cards/b/BrazenFreebooter.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BrazenFreebooter.java diff --git a/Mage.Sets/src/mage/cards/b/BrazenFreebooter.java b/Mage.Sets/src/mage/cards/b/BrazenFreebooter.java new file mode 100644 index 00000000000..88b9bc2c9f8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BrazenFreebooter.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.TreasureToken; + +/** + * + * @author L_J + */ +public class BrazenFreebooter extends CardImpl { + + public BrazenFreebooter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PIRATE); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Brazen Freebooter enters the battlefield, create a colorless Treasure artifact token with "T, sacrifice this artifact: Add one mana of any color to your mana pool." + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken()), false)); + } + + public BrazenFreebooter(final BrazenFreebooter card) { + super(card); + } + + @Override + public BrazenFreebooter copy() { + return new BrazenFreebooter(this); + } +} From 1459d8fc905c1f3381bbf81fdc40082c5cbd7e62 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 13:34:25 +0000 Subject: [PATCH 04/71] Implemented Buccaneer's Bravado --- .../src/mage/cards/b/BuccaneersBravado.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BuccaneersBravado.java diff --git a/Mage.Sets/src/mage/cards/b/BuccaneersBravado.java b/Mage.Sets/src/mage/cards/b/BuccaneersBravado.java new file mode 100644 index 00000000000..64b605a4a16 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BuccaneersBravado.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class BuccaneersBravado extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("Pirate"); + + static { + filter.add(new SubtypePredicate(SubType.PIRATE)); + } + + public BuccaneersBravado(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); + + // Choose one - + // Target creature gets +1/+1 and gains first strike until end of turn. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn).setText("Target creature gets +1/+1")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn).setText("and gains first strike until end of turn")); + // Target Pirate gets +1/+1 and gains double strike until end of turn. + Mode mode = new Mode(); + mode.getTargets().add(new TargetPermanent(filter)); + mode.getEffects().add(new BoostTargetEffect(1, 1, Duration.EndOfTurn).setText("Target Pirate gets +1/+1")); + mode.getEffects().add(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn).setText("and gains double strike until end of turn")); + this.getSpellAbility().addMode(mode); + } + + public BuccaneersBravado(final BuccaneersBravado card) { + super(card); + } + + @Override + public BuccaneersBravado copy() { + return new BuccaneersBravado(this); + } +} From 590717c12e0539ad98a9510371cef59adb432ed2 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 13:38:08 +0000 Subject: [PATCH 05/71] [RIX] Added 4 cards --- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 28cf7825bb8..13050ba4766 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -61,13 +61,17 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Angrath, Minotaur Pirate", 201, Rarity.MYTHIC, mage.cards.a.AngrathMinotaurPirate.class)); cards.add(new SetCardInfo("Angrath's Ambusher", 202, Rarity.UNCOMMON, mage.cards.a.AngrathsAmbusher.class)); cards.add(new SetCardInfo("Angrath's Fury", 204, Rarity.RARE, mage.cards.a.AngrathsFury.class)); + cards.add(new SetCardInfo("Aquatic Incursion", 32, Rarity.UNCOMMON, mage.cards.a.AquaticIncursion.class)); cards.add(new SetCardInfo("Arterial Flow", 62, Rarity.UNCOMMON, mage.cards.a.ArterialFlow.class)); cards.add(new SetCardInfo("Atzal, Cave of Eternity", "160b", Rarity.RARE, mage.cards.a.AtzalCaveOfEternity.class)); cards.add(new SetCardInfo("Atzocan Seer", "153a", Rarity.UNCOMMON, mage.cards.a.AtzocanSeer.class)); cards.add(new SetCardInfo("Azor's Gateway", 176, Rarity.MYTHIC, mage.cards.a.AzorsGateway.class)); + cards.add(new SetCardInfo("Azor, the Lawbringer", 154, Rarity.MYTHIC, mage.cards.a.AzorTheLawbringer.class)); cards.add(new SetCardInfo("Baffling End", 1, Rarity.UNCOMMON, mage.cards.b.BafflingEnd.class)); cards.add(new SetCardInfo("Bombard", 93, Rarity.COMMON, mage.cards.b.Bombard.class)); cards.add(new SetCardInfo("Brass's Bounty", 94, Rarity.RARE, mage.cards.b.BrasssBounty.class)); + cards.add(new SetCardInfo("Brazen Freebooter", 95, Rarity.COMMON, mage.cards.b.BrazenFreebooter.class)); + cards.add(new SetCardInfo("Buccaneer's Bravado", 96, Rarity.COMMON, mage.cards.b.BuccaneersBravado.class)); cards.add(new SetCardInfo("Cacophodon", 123, Rarity.UNCOMMON, mage.cards.c.Cacophodon.class)); cards.add(new SetCardInfo("Canal Monitor", 63, Rarity.COMMON, mage.cards.c.CanalMonitor.class)); cards.add(new SetCardInfo("Captain's Hook", 177, Rarity.RARE, mage.cards.c.CaptainsHook.class)); From 690c04f5fc01cfbd54956025bcfe6022a973680e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 15:05:20 +0100 Subject: [PATCH 06/71] [RIX] Added 3 cards. --- .../dl/sources/MythicspoilerComSource.java | 5 + .../src/mage/cards/b/BishopOfBinding.java | 152 ++++++++++++++++++ Mage.Sets/src/mage/cards/b/BlazingHope.java | 123 ++++++++++++++ Mage.Sets/src/mage/cards/b/BloodSun.java | 125 ++++++++++++++ Mage.Sets/src/mage/cards/g/GruesomeFate.java | 2 +- .../mage/cards/s/SecretsOfTheGoldenCity.java | 134 +++++++-------- 6 files changed, 473 insertions(+), 68 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/b/BishopOfBinding.java create mode 100644 Mage.Sets/src/mage/cards/b/BlazingHope.java create mode 100644 Mage.Sets/src/mage/cards/b/BloodSun.java diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index a5f9412ceae..e625219ae74 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -301,6 +301,11 @@ public enum MythicspoilerComSource implements CardImageSource { HashMap linksRix = new HashMap<>(); linksRix.put("vaultofcatlacan", "vaultofcatlacan"); linksRix.put("atzalcaveofeternity", "atzalcaveofeternity"); + linksRix.put("wingedtempleoforazca", "wingedtempleoforazca"); + linksRix.put("metzalitoweroftriumph", "metzalitoweroftriumph"); + linksRix.put("tomboftheduskrose", "tomboftheduskrose"); + linksRix.put("sanctumofthesun", "sanctumofthesun"); + linksRix.put("goldforgegarrison", "goldforgegarrison"); manualLinks.put("RIX", linksRix); cardNameAliasesStart = new HashMap<>(); diff --git a/Mage.Sets/src/mage/cards/b/BishopOfBinding.java b/Mage.Sets/src/mage/cards/b/BishopOfBinding.java new file mode 100644 index 00000000000..903d923eab7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BishopOfBinding.java @@ -0,0 +1,152 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class BishopOfBinding extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls"); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public BishopOfBinding(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Bishop of Binding enters the battlefield, exile target creature an opponent controls until Bishop of Binding leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new BishopOfBindingExileEffect()); + ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); + this.addAbility(ability); + + // Whenever Bishop of Binding attacks, target Vampire gets +X/+X until end of turn, where X is the power of the exiled card. + DynamicValue xVale = new BishopOfBindingExiledCardsPowerCount(); + ability = new AttacksTriggeredAbility(new BoostTargetEffect(xVale, xVale, Duration.EndOfTurn, true) + .setText("target Vampire gets +X/+X until end of turn, where X is the power of the exiled card"), false); + ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent(SubType.VAMPIRE, "Vampire"))); + this.addAbility(ability); + } + + public BishopOfBinding(final BishopOfBinding card) { + super(card); + } + + @Override + public BishopOfBinding copy() { + return new BishopOfBinding(this); + } +} + +class BishopOfBindingExileEffect extends OneShotEffect { + + public BishopOfBindingExileEffect() { + super(Outcome.Benefit); + this.staticText = "exile target creature an opponent controls until {this} leaves the battlefield"; + } + + public BishopOfBindingExileEffect(final BishopOfBindingExileEffect effect) { + super(effect); + } + + @Override + public BishopOfBindingExileEffect copy() { + return new BishopOfBindingExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = (Permanent) source.getSourceObjectIfItStillExists(game); + // If this leaves the battlefield before its triggered ability resolves, + // the target creature won't be exiled. + if (permanent != null) { + return new ExileTargetEffect(CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), permanent.getIdName()).apply(game, source); + } + return false; + } +} + +class BishopOfBindingExiledCardsPowerCount implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, sourceAbility.getSourceId(), sourceAbility.getSourceObjectZoneChangeCounter())); + Card exiledCard = exileZone.getRandom(game); + if (exiledCard != null) { + return exiledCard.getPower().getValue(); + } + return 0; + } + + @Override + public BishopOfBindingExiledCardsPowerCount copy() { + return new BishopOfBindingExiledCardsPowerCount(); + } + + @Override + public String getMessage() { + return "power of the exiled card"; + } + +} diff --git a/Mage.Sets/src/mage/cards/b/BlazingHope.java b/Mage.Sets/src/mage/cards/b/BlazingHope.java new file mode 100644 index 00000000000..17226da746a --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlazingHope.java @@ -0,0 +1,123 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class BlazingHope extends CardImpl { + + public BlazingHope(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + // Exile target creature with power greater than or equal to your life total. + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addTarget(new BlazingHopeTarget()); + } + + public BlazingHope(final BlazingHope card) { + super(card); + } + + @Override + public BlazingHope copy() { + return new BlazingHope(this); + } +} + +class BlazingHopeTarget extends TargetCreaturePermanent { + + public BlazingHopeTarget() { + super(new FilterCreaturePermanent("creature with power greater than or equal to your life total")); + } + + public BlazingHopeTarget(final BlazingHopeTarget target) { + super(target); + } + + @Override + public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + Permanent permanent = game.getPermanent(id); + if (permanent != null) { + if (!isNotTarget()) { + if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) + || !permanent.canBeTargetedBy(game.getObject(source.getSourceId()), controllerId, game)) { + return false; + } + } + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && permanent.getPower().getValue() >= controller.getLife()) { + return filter.match(permanent, source.getSourceId(), controllerId, game); + } + } + return false; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + int remainingTargets = this.minNumberOfTargets - targets.size(); + if (remainingTargets <= 0) { + return true; + } + int count = 0; + Player controller = game.getPlayer(sourceControllerId); + MageObject targetSource = game.getObject(sourceId); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + if (!targets.containsKey(permanent.getId())) { + if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { + if (controller != null && permanent.getPower().getValue() >= controller.getLife()) { + count++; + if (count >= remainingTargets) { + return true; + } + } + } + } + } + return false; + } + + @Override + public BlazingHopeTarget copy() { + return new BlazingHopeTarget(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BloodSun.java b/Mage.Sets/src/mage/cards/b/BloodSun.java new file mode 100644 index 00000000000..d72953070a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BloodSun.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.Iterator; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.AbilityAddingRemovingEffects_6; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class BloodSun extends CardImpl { + + public BloodSun(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + + // When Blood Sun enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); + + // All lands lose all abilities except mana abilities. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BloodSunEffect(Duration.WhileOnBattlefield))); + } + + public BloodSun(final BloodSun card) { + super(card); + } + + @Override + public BloodSun copy() { + return new BloodSun(this); + } +} + +class BloodSunEffect extends ContinuousEffectImpl { + + public BloodSunEffect(Duration duration) { + super(duration, Outcome.LoseAbility); + staticText = "all lands lose all abilities except mana abilities"; + } + + public BloodSunEffect(final BloodSunEffect effect) { + super(effect); + } + + @Override + public BloodSunEffect copy() { + return new BloodSunEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS, player.getId(), source.getSourceId(), game)) { + switch (layer) { + case AbilityAddingRemovingEffects_6: + for (Iterator it = permanent.getAbilities().iterator(); it.hasNext();) { + Ability ability = it.next(); + if (!ability.getAbilityType().equals(AbilityType.MANA)) { + it.remove(); + } + } + break; + } + } + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.AbilityAddingRemovingEffects_6; + } + +} diff --git a/Mage.Sets/src/mage/cards/g/GruesomeFate.java b/Mage.Sets/src/mage/cards/g/GruesomeFate.java index 43e6d874240..d9eb6b1d63a 100644 --- a/Mage.Sets/src/mage/cards/g/GruesomeFate.java +++ b/Mage.Sets/src/mage/cards/g/GruesomeFate.java @@ -44,7 +44,7 @@ import mage.filter.predicate.permanent.ControllerPredicate; public class GruesomeFate extends CardImpl { public GruesomeFate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{5}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); // Each opponent loses 1 life for each creature you control. FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control"); diff --git a/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java b/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java index 175a0ce9662..936e68a29b5 100644 --- a/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java +++ b/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java @@ -1,67 +1,67 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.cards.s; - -import java.util.UUID; -import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.common.discard.DiscardControllerEffect; -import mage.abilities.effects.keyword.AscendEffect; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; - -/** - * - * @author LevelX2 - */ -public class SecretsOfTheGoldenCity extends CardImpl { - - public SecretsOfTheGoldenCity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}"); - - // Ascend - this.getSpellAbility().addEffect(new AscendEffect()); - - // Draw two cards. If you have the city's blessing, draw three cards instead. - this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DiscardControllerEffect(3), - new DiscardControllerEffect(2), - CitysBlessingCondition.instance, - "Draw two cards. If you have the city's blessing, draw three cards instead")); - } - - public SecretsOfTheGoldenCity(final SecretsOfTheGoldenCity card) { - super(card); - } - - @Override - public SecretsOfTheGoldenCity copy() { - return new SecretsOfTheGoldenCity(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.condition.common.CitysBlessingCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.keyword.AscendEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author LevelX2 + */ +public class SecretsOfTheGoldenCity extends CardImpl { + + public SecretsOfTheGoldenCity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}"); + + // Ascend + this.getSpellAbility().addEffect(new AscendEffect()); + + // Draw two cards. If you have the city's blessing, draw three cards instead. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(3), + new DrawCardSourceControllerEffect(2), + CitysBlessingCondition.instance, + "Draw two cards. If you have the city's blessing, draw three cards instead")); + } + + public SecretsOfTheGoldenCity(final SecretsOfTheGoldenCity card) { + super(card); + } + + @Override + public SecretsOfTheGoldenCity copy() { + return new SecretsOfTheGoldenCity(this); + } +} From ca11def7144d02f718a2121a188bbd8a3ce9542e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 15:05:27 +0100 Subject: [PATCH 07/71] [RIX] Added 3 cards. --- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 13050ba4766..2c3212d5612 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -68,6 +68,9 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Azor's Gateway", 176, Rarity.MYTHIC, mage.cards.a.AzorsGateway.class)); cards.add(new SetCardInfo("Azor, the Lawbringer", 154, Rarity.MYTHIC, mage.cards.a.AzorTheLawbringer.class)); cards.add(new SetCardInfo("Baffling End", 1, Rarity.UNCOMMON, mage.cards.b.BafflingEnd.class)); + cards.add(new SetCardInfo("Bishop of Binding", 2, Rarity.RARE, mage.cards.b.BishopOfBinding.class)); + cards.add(new SetCardInfo("Blazing Hope", 3, Rarity.UNCOMMON, mage.cards.b.BlazingHope.class)); + cards.add(new SetCardInfo("Blood Sun", 92, Rarity.RARE, mage.cards.b.BloodSun.class)); cards.add(new SetCardInfo("Bombard", 93, Rarity.COMMON, mage.cards.b.Bombard.class)); cards.add(new SetCardInfo("Brass's Bounty", 94, Rarity.RARE, mage.cards.b.BrasssBounty.class)); cards.add(new SetCardInfo("Brazen Freebooter", 95, Rarity.COMMON, mage.cards.b.BrazenFreebooter.class)); From 4898c75bbd7f946676b7f0e8aced87c59fcf1c4a Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 15:19:18 +0100 Subject: [PATCH 08/71] [RIX] Added 2 cards. --- Mage.Sets/src/mage/cards/a/ArchOfOrazca.java | 76 ++++++++++++ .../src/mage/cards/a/AwakenedAmalgam.java | 108 ++++++++++++++++++ Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 2 + 3 files changed, 186 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/ArchOfOrazca.java create mode 100644 Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java diff --git a/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java b/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java new file mode 100644 index 00000000000..2ea72b466dc --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.CitysBlessingCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.AscendAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class ArchOfOrazca extends CardImpl { + + public ArchOfOrazca(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Ascend + this.addAbility(new AscendAbility()); + + // {t}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {5}, {T}: Draw a card. Activate this ability only if you have the city's blessing. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(1), + new GenericManaCost(5), + CitysBlessingCondition.instance); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public ArchOfOrazca(final ArchOfOrazca card) { + super(card); + } + + @Override + public ArchOfOrazca copy() { + return new ArchOfOrazca(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java b/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java new file mode 100644 index 00000000000..80da89ac90b --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AwakenedAmalgam.java @@ -0,0 +1,108 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.HashSet; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class AwakenedAmalgam extends CardImpl { + + public AwakenedAmalgam(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + + this.subtype.add(SubType.GOLEM); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Awakened Amalgam's power and toughness are each equal to the number of differently named lands you control. + DynamicValue value = (new AwakenedAmalgamLandNamesCount()); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(value, Duration.EndOfGame))); + } + + public AwakenedAmalgam(final AwakenedAmalgam card) { + super(card); + } + + @Override + public AwakenedAmalgam copy() { + return new AwakenedAmalgam(this); + } +} + +class AwakenedAmalgamLandNamesCount implements DynamicValue { + + public AwakenedAmalgamLandNamesCount() { + } + + public AwakenedAmalgamLandNamesCount(AwakenedAmalgamLandNamesCount dynamicValue) { + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + HashSet landNames = new HashSet<>(); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(sourceAbility.getControllerId())) { + if (permanent.isLand()) { + landNames.add(permanent.getName()); + } + } + return landNames.size(); + } + + @Override + public AwakenedAmalgamLandNamesCount copy() { + return new AwakenedAmalgamLandNamesCount(this); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "differently named lands you control"; + } +} diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 2c3212d5612..f5d72724386 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -62,9 +62,11 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Angrath's Ambusher", 202, Rarity.UNCOMMON, mage.cards.a.AngrathsAmbusher.class)); cards.add(new SetCardInfo("Angrath's Fury", 204, Rarity.RARE, mage.cards.a.AngrathsFury.class)); cards.add(new SetCardInfo("Aquatic Incursion", 32, Rarity.UNCOMMON, mage.cards.a.AquaticIncursion.class)); + cards.add(new SetCardInfo("Arch of Orazca", 185, Rarity.RARE, mage.cards.a.ArchOfOrazca.class)); cards.add(new SetCardInfo("Arterial Flow", 62, Rarity.UNCOMMON, mage.cards.a.ArterialFlow.class)); cards.add(new SetCardInfo("Atzal, Cave of Eternity", "160b", Rarity.RARE, mage.cards.a.AtzalCaveOfEternity.class)); cards.add(new SetCardInfo("Atzocan Seer", "153a", Rarity.UNCOMMON, mage.cards.a.AtzocanSeer.class)); + cards.add(new SetCardInfo("Awakened Amalgam", 175, Rarity.RARE, mage.cards.a.AwakenedAmalgam.class)); cards.add(new SetCardInfo("Azor's Gateway", 176, Rarity.MYTHIC, mage.cards.a.AzorsGateway.class)); cards.add(new SetCardInfo("Azor, the Lawbringer", 154, Rarity.MYTHIC, mage.cards.a.AzorTheLawbringer.class)); cards.add(new SetCardInfo("Baffling End", 1, Rarity.UNCOMMON, mage.cards.b.BafflingEnd.class)); From 682de367a032bec23a2ce61e553a5bc72c4d33aa Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 15:50:19 +0100 Subject: [PATCH 09/71] [RIX] Added Angrath, the Flame-Chained. Set complete! --- .../mage/cards/a/AngrathTheFlameChained.java | 190 ++++++++++++++++++ Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 1 + 2 files changed, 191 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java diff --git a/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java b/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java new file mode 100644 index 00000000000..20433552d0b --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java @@ -0,0 +1,190 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class AngrathTheFlameChained extends CardImpl { + + public AngrathTheFlameChained(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{B}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ANGRATH); + this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(4)); + + // +1: Each opponent discards a card and loses 2 life. + LoyaltyAbility ability = new LoyaltyAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), 1); + ability.addEffect(new LoseLifeOpponentsEffect(2)); + this.addAbility(ability); + + // -3: Gain control of target creature until end of turn. Untap it. It gains haste until end of turn. Sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less. + ability = new LoyaltyAbility(new GainControlTargetEffect(Duration.EndOfTurn), -3); + ability.addEffect(new UntapTargetEffect().setText("untap it")); + ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("It gains haste until end of turn")); + ability.addEffect(new AngrathTheFlameCreateDelayedTriggerEffect()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // -8: Each opponent loses life equal to the number of cards in his or her graveyard. + this.addAbility(new LoyaltyAbility(new AngrathTheFlameUltimateEffect(), -8)); + + } + + public AngrathTheFlameChained(final AngrathTheFlameChained card) { + super(card); + } + + @Override + public AngrathTheFlameChained copy() { + return new AngrathTheFlameChained(this); + } +} + +class AngrathTheFlameUltimateEffect extends OneShotEffect { + + public AngrathTheFlameUltimateEffect() { + super(Outcome.Benefit); + this.staticText = "Each opponent loses life equal to the number of cards in his or her graveyard"; + } + + public AngrathTheFlameUltimateEffect(final AngrathTheFlameUltimateEffect effect) { + super(effect); + } + + @Override + public AngrathTheFlameUltimateEffect copy() { + return new AngrathTheFlameUltimateEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + Player player = game.getPlayer(opponentId); + if (player != null && !player.getGraveyard().isEmpty()) { + player.loseLife(player.getGraveyard().size(), game, false); + } + } + return true; + } +} + +class AngrathTheFlameCreateDelayedTriggerEffect extends OneShotEffect { + + public AngrathTheFlameCreateDelayedTriggerEffect() { + super(Outcome.Sacrifice); + staticText = "Sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less"; + } + + public AngrathTheFlameCreateDelayedTriggerEffect(final AngrathTheFlameCreateDelayedTriggerEffect effect) { + super(effect); + } + + @Override + public AngrathTheFlameCreateDelayedTriggerEffect copy() { + return new AngrathTheFlameCreateDelayedTriggerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice this", source.getControllerId()); + sacrificeEffect.setTargetPointer(new FixedTarget(permanent, game)); + DelayedTriggeredAbility delayedAbility = new AngrathTheFlameChainedDelayedTriggeredAbility(sacrificeEffect); + game.addDelayedTriggeredAbility(delayedAbility, source); + return true; + } + return false; + } +} + +class AngrathTheFlameChainedDelayedTriggeredAbility extends DelayedTriggeredAbility { + + public AngrathTheFlameChainedDelayedTriggeredAbility(Effect effect) { + super(effect, Duration.Custom); + } + + public AngrathTheFlameChainedDelayedTriggeredAbility(final AngrathTheFlameChainedDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.END_TURN_STEP_PRE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(((FixedTarget) getEffects().get(0).getTargetPointer()).getTarget()); + return permanent != null + && permanent.getZoneChangeCounter(game) == ((FixedTarget) getEffects().get(0).getTargetPointer()).getZoneChangeCounter() + && permanent.getConvertedManaCost() >= 3; + } + + @Override + public AngrathTheFlameChainedDelayedTriggeredAbility copy() { + return new AngrathTheFlameChainedDelayedTriggeredAbility(this); + } + + @Override + public String getRule() { + return "sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less."; + } +} diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index f5d72724386..6a8c48f4428 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -61,6 +61,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Angrath, Minotaur Pirate", 201, Rarity.MYTHIC, mage.cards.a.AngrathMinotaurPirate.class)); cards.add(new SetCardInfo("Angrath's Ambusher", 202, Rarity.UNCOMMON, mage.cards.a.AngrathsAmbusher.class)); cards.add(new SetCardInfo("Angrath's Fury", 204, Rarity.RARE, mage.cards.a.AngrathsFury.class)); + cards.add(new SetCardInfo("Angrath, the Flame-Chained", 152, Rarity.MYTHIC, mage.cards.a.AngrathTheFlameChained.class)); cards.add(new SetCardInfo("Aquatic Incursion", 32, Rarity.UNCOMMON, mage.cards.a.AquaticIncursion.class)); cards.add(new SetCardInfo("Arch of Orazca", 185, Rarity.RARE, mage.cards.a.ArchOfOrazca.class)); cards.add(new SetCardInfo("Arterial Flow", 62, Rarity.UNCOMMON, mage.cards.a.ArterialFlow.class)); From 9c77a5db7a43658282ac11aca106c8aabc5dbf66 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:13:34 +0000 Subject: [PATCH 10/71] Added currency counter --- Mage/src/main/java/mage/counters/CounterType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 3b3f8f2f5d5..deebfd47d01 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -49,6 +49,7 @@ public enum CounterType { CREDIT("credit"), CRYSTAL("crystal"), CUBE("cube"), + CURRENCY("currency"), DELAY("delay"), DEPLETION("depletion"), DESPAIR("despair"), From ba8843115b34ea971c08c13ca4a87f0fb12e4caf Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:34:12 +0000 Subject: [PATCH 11/71] Implemented Trade Caravan --- Mage.Sets/src/mage/cards/t/TradeCaravan.java | 91 ++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TradeCaravan.java diff --git a/Mage.Sets/src/mage/cards/t/TradeCaravan.java b/Mage.Sets/src/mage/cards/t/TradeCaravan.java new file mode 100644 index 00000000000..44bc2dd773d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TradeCaravan.java @@ -0,0 +1,91 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.common.IsStepCondition; +import mage.abilities.condition.common.OnOpponentsTurnCondition; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.PhaseStep; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author L_J + */ +public class TradeCaravan extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent("basic land"); + + static { + filter.add(new SupertypePredicate(SuperType.BASIC)); + } + + public TradeCaravan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOMAD); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // At the beginning of your upkeep, put a currency counter on Trade Caravan. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CURRENCY.createInstance()), TargetController.YOU, false)); + // Remove two currency counters from Trade Caravan: Untap target basic land. Activate this ability only during an opponent's upkeep. + Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new RemoveCountersSourceCost(CounterType.CURRENCY.createInstance(2)), + new CompoundCondition(OnOpponentsTurnCondition.instance, new IsStepCondition(PhaseStep.UPKEEP, false)), + "Remove two currency counters from {this}: Untap target basic land. Activate this ability only during an opponent's upkeep."); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public TradeCaravan(final TradeCaravan card) { + super(card); + } + + @Override + public TradeCaravan copy() { + return new TradeCaravan(this); + } +} From a3e33b7d3f0e2e09eed389e5a4c69bbd4ad41897 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:35:29 +0000 Subject: [PATCH 12/71] Implemented Truce --- Mage.Sets/src/mage/cards/t/Truce.java | 95 +++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/Truce.java diff --git a/Mage.Sets/src/mage/cards/t/Truce.java b/Mage.Sets/src/mage/cards/t/Truce.java new file mode 100644 index 00000000000..cbe1b0a472a --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/Truce.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author L_J + */ +public class Truce extends CardImpl { + + public Truce(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}"); + + // Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life. + this.getSpellAbility().addEffect(new TruceEffect()); + } + + public Truce(final Truce card) { + super(card); + } + + @Override + public Truce copy() { + return new Truce(this); + } +} + +class TruceEffect extends OneShotEffect { + + TruceEffect() { + super(Outcome.DrawCard); + this.staticText = "Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life"; + } + + TruceEffect(final TruceEffect effect) { + super(effect); + } + + @Override + public TruceEffect copy() { + return new TruceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + int cardsToDraw = player.getAmount(0, 2, "Draw how many cards?", game); + player.drawCards(cardsToDraw, game); + player.gainLife((2 - cardsToDraw) * 2, game); + } + } + return true; + } + return false; + } +} From f1bea8ee4ca96235db9a456a96334d80340f4745 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:36:32 +0000 Subject: [PATCH 13/71] Implemented Indentured Djinn --- .../src/mage/cards/i/IndenturedDjinn.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/IndenturedDjinn.java diff --git a/Mage.Sets/src/mage/cards/i/IndenturedDjinn.java b/Mage.Sets/src/mage/cards/i/IndenturedDjinn.java new file mode 100644 index 00000000000..a2e1a19850c --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IndenturedDjinn.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public class IndenturedDjinn extends CardImpl { + + public IndenturedDjinn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{U}"); + this.subtype.add(SubType.DJINN); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Indentured Djinn enters the battlefield, each other player may draw up to three cards. + this.addAbility(new EntersBattlefieldTriggeredAbility(new IndenturedDjinnEffect(), false)); + } + + public IndenturedDjinn(final IndenturedDjinn card) { + super(card); + } + + @Override + public IndenturedDjinn copy() { + return new IndenturedDjinn(this); + } +} + +class IndenturedDjinnEffect extends OneShotEffect { + + IndenturedDjinnEffect() { + super(Outcome.DrawCard); + this.staticText = "each other player may draw up to three cards"; + } + + IndenturedDjinnEffect(final IndenturedDjinnEffect effect) { + super(effect); + } + + @Override + public IndenturedDjinnEffect copy() { + return new IndenturedDjinnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player player = game.getPlayer(playerId); + if (player != null) { + Effect effect = new DrawCardTargetEffect(new StaticValue(3), false, true); + effect.setTargetPointer(new FixedTarget(playerId)); + effect.setText(player.getLogName() + " may draw up to three cards"); + effect.apply(game, source); + } + } + return true; + } + return false; + } +} From de46891d746ff1a70911adb2bdc1e07d9515b6c8 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:38:12 +0000 Subject: [PATCH 14/71] Implemented Indenttured Djinn --- Mage.Sets/src/mage/sets/FifthEdition.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/FifthEdition.java b/Mage.Sets/src/mage/sets/FifthEdition.java index 1afb371eef6..244e1875feb 100644 --- a/Mage.Sets/src/mage/sets/FifthEdition.java +++ b/Mage.Sets/src/mage/sets/FifthEdition.java @@ -411,6 +411,7 @@ public class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Torture", 61, Rarity.COMMON, Torture.class)); cards.add(new SetCardInfo("Touch of Death", 62, Rarity.COMMON, mage.cards.t.TouchOfDeath.class)); cards.add(new SetCardInfo("Tranquility", 195, Rarity.COMMON, mage.cards.t.Tranquility.class)); + cards.add(new SetCardInfo("Truce", 341, Rarity.RARE, mage.cards.t.Truce.class)); cards.add(new SetCardInfo("Tsunami", 196, Rarity.UNCOMMON, mage.cards.t.Tsunami.class)); cards.add(new SetCardInfo("Tundra Wolves", 342, Rarity.COMMON, mage.cards.t.TundraWolves.class)); cards.add(new SetCardInfo("Twiddle", 130, Rarity.COMMON, mage.cards.t.Twiddle.class)); From 0faf22455a1abfff3a764171ec19187025bce6e3 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:40:17 +0000 Subject: [PATCH 15/71] Implemented Indentured Djinn --- Mage.Sets/src/mage/sets/MercadianMasques.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index e61b95875c7..5ca90702ace 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -186,6 +186,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Howling Wolf", 252, Rarity.COMMON, mage.cards.h.HowlingWolf.class)); cards.add(new SetCardInfo("Hunted Wumpus", 253, Rarity.UNCOMMON, mage.cards.h.HuntedWumpus.class)); cards.add(new SetCardInfo("Ignoble Soldier", 22, Rarity.UNCOMMON, mage.cards.i.IgnobleSoldier.class)); + cards.add(new SetCardInfo("Indentured Djinn", 85, Rarity.UNCOMMON, mage.cards.i.IndenturedDjinn.class)); cards.add(new SetCardInfo("Instigator", 140, Rarity.RARE, mage.cards.i.Instigator.class)); cards.add(new SetCardInfo("Intimidation", 142, Rarity.UNCOMMON, mage.cards.i.Intimidation.class)); cards.add(new SetCardInfo("Invigorate", 254, Rarity.COMMON, mage.cards.i.Invigorate.class)); From e4f113c035d634d9826ffadcd804b8f92ea83ae6 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Sun, 7 Jan 2018 16:41:06 +0000 Subject: [PATCH 16/71] Implemented Trade Caravan and Truce --- Mage.Sets/src/mage/sets/Homelands.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mage.Sets/src/mage/sets/Homelands.java b/Mage.Sets/src/mage/sets/Homelands.java index 2a5cb439a87..4209ae62825 100644 --- a/Mage.Sets/src/mage/sets/Homelands.java +++ b/Mage.Sets/src/mage/sets/Homelands.java @@ -171,6 +171,9 @@ public class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Spectral Bears", 72, Rarity.UNCOMMON, mage.cards.s.SpectralBears.class)); cards.add(new SetCardInfo("Torture", 23, Rarity.COMMON, Torture.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Torture", 24, Rarity.COMMON, Torture.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Trade Caravan", 123, Rarity.COMMON, mage.cards.t.TradeCaravan.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Trade Caravan", 124, Rarity.COMMON, mage.cards.t.TradeCaravan.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Truce", 125, Rarity.RARE, mage.cards.t.Truce.class)); cards.add(new SetCardInfo("Veldrane of Sengir", 25, Rarity.RARE, mage.cards.v.VeldraneOfSengir.class)); cards.add(new SetCardInfo("Wall of Kelp", 50, Rarity.RARE, mage.cards.w.WallOfKelp.class)); cards.add(new SetCardInfo("Willow Faerie", 73, Rarity.COMMON, WillowFaerie.class, NON_FULL_USE_VARIOUS)); From 8afcc63b841353e8dadba5dca0ac8f7e4885c159 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 18:03:37 +0100 Subject: [PATCH 17/71] [RIX] Some minor fixes --- .../mage/cards/a/AngrathTheFlameChained.java | 2 +- .../src/mage/cards/c/CherishedHatchling.java | 112 ++++++++++-------- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 34 +++--- 3 files changed, 80 insertions(+), 68 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java b/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java index 20433552d0b..efb1758fb04 100644 --- a/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java +++ b/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java @@ -71,7 +71,7 @@ public class AngrathTheFlameChained extends CardImpl { // +1: Each opponent discards a card and loses 2 life. LoyaltyAbility ability = new LoyaltyAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), 1); - ability.addEffect(new LoseLifeOpponentsEffect(2)); + ability.addEffect(new LoseLifeOpponentsEffect(2).setText("and loses 2 life")); this.addAbility(ability); // -3: Gain control of target creature until end of turn. Untap it. It gains haste until end of turn. Sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less. diff --git a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java index a263a03edcd..6907711ae04 100644 --- a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java +++ b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java @@ -33,19 +33,15 @@ import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashAllEffect; -import mage.cards.Card; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; @@ -94,8 +90,22 @@ public class CherishedHatchling extends CardImpl { class CherishedHatchlingTriggeredAbility extends DelayedTriggeredAbility { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); + + static { + filter.add(new AnotherPredicate()); + } + public CherishedHatchlingTriggeredAbility() { - super(new CherishedHatchlingGainAbilityEffect(), Duration.EndOfTurn, true); + super(getEffectToAdd(), Duration.EndOfTurn, true); + } + + private static Effect getEffectToAdd() { + Ability abilityToAdd = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect().setText("you may have it fight another target creature"), true); + abilityToAdd.addTarget(new TargetCreaturePermanent(filter)); + Effect effect = new GainAbilityTargetEffect(abilityToAdd, Duration.EndOfTurn, + "it gains \"When this creature enters the battlefield, you may have it fight another target creature.\"", true); + return effect; } private CherishedHatchlingTriggeredAbility(final CherishedHatchlingTriggeredAbility ability) { @@ -117,7 +127,7 @@ class CherishedHatchlingTriggeredAbility extends DelayedTriggeredAbility { if (event.getPlayerId().equals(this.getControllerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.isCreature() && spell.hasSubtype(SubType.DINOSAUR, game)) { - getEffects().setTargetPointer(new FixedTarget(spell.getId())); + getEffects().setTargetPointer(new FixedTarget(spell.getSourceId())); return true; } } @@ -130,47 +140,47 @@ class CherishedHatchlingTriggeredAbility extends DelayedTriggeredAbility { } } -class CherishedHatchlingGainAbilityEffect extends ContinuousEffectImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - - static { - filter.add(new AnotherPredicate()); - } - private Ability abilityToAdd = null; - private Card relatedCard = null; - - public CherishedHatchlingGainAbilityEffect() { - super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); - staticText = "it gains \"When this creature enters the battlefield, you may have it fight another target creature.\""; - } - - public CherishedHatchlingGainAbilityEffect(final CherishedHatchlingGainAbilityEffect effect) { - super(effect); - this.abilityToAdd = effect.abilityToAdd; - this.relatedCard = effect.relatedCard; - } - - @Override - public CherishedHatchlingGainAbilityEffect copy() { - return new CherishedHatchlingGainAbilityEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - if (relatedCard == null) { - Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); - if (spell != null) { - relatedCard = game.getCard(spell.getSourceId()); - Effect effect = new FightTargetSourceEffect(); - effect.setText("you may have it fight another target creature"); - abilityToAdd = new EntersBattlefieldTriggeredAbility(effect, true); - abilityToAdd.addTarget(new TargetCreaturePermanent(filter)); - } - } - if (relatedCard != null) { - game.getState().addOtherAbility(relatedCard, abilityToAdd, false); - } - return true; - } -} +//class CherishedHatchlingGainAbilityEffect extends ContinuousEffectImpl { +// +// private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); +// +// static { +// filter.add(new AnotherPredicate()); +// } +// private Ability abilityToAdd = null; +// private Card relatedCard = null; +// +// public CherishedHatchlingGainAbilityEffect() { +// super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); +// staticText = "it gains \"When this creature enters the battlefield, you may have it fight another target creature.\""; +// } +// +// public CherishedHatchlingGainAbilityEffect(final CherishedHatchlingGainAbilityEffect effect) { +// super(effect); +// this.abilityToAdd = effect.abilityToAdd; +// this.relatedCard = effect.relatedCard; +// } +// +// @Override +// public CherishedHatchlingGainAbilityEffect copy() { +// return new CherishedHatchlingGainAbilityEffect(this); +// } +// +// @Override +// public boolean apply(Game game, Ability source) { +// if (relatedCard == null) { +// Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); +// if (spell != null) { +// relatedCard = game.getCard(spell.getSourceId()); +// Effect effect = new FightTargetSourceEffect(); +// effect.setText("you may have it fight another target creature"); +// abilityToAdd = new EntersBattlefieldTriggeredAbility(effect, true); +// abilityToAdd.addTarget(new TargetCreaturePermanent(filter)); +// } +// } +// if (relatedCard != null) { +// game.getState().addOtherAbility(relatedCard, abilityToAdd, false); +// } +// return true; +// } +//} diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 6a8c48f4428..4ec8d0df626 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -55,6 +55,8 @@ public class RivalsOfIxalan extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; + this.numBoosterDoubleFaced = -1; + this.maxCardNumberInBooster = 196; cards.add(new SetCardInfo("Admiral's Order", 31, Rarity.RARE, mage.cards.a.AdmiralsOrder.class)); cards.add(new SetCardInfo("Aggressive Urge", 122, Rarity.COMMON, mage.cards.a.AggressiveUrge.class)); @@ -65,10 +67,10 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Aquatic Incursion", 32, Rarity.UNCOMMON, mage.cards.a.AquaticIncursion.class)); cards.add(new SetCardInfo("Arch of Orazca", 185, Rarity.RARE, mage.cards.a.ArchOfOrazca.class)); cards.add(new SetCardInfo("Arterial Flow", 62, Rarity.UNCOMMON, mage.cards.a.ArterialFlow.class)); - cards.add(new SetCardInfo("Atzal, Cave of Eternity", "160b", Rarity.RARE, mage.cards.a.AtzalCaveOfEternity.class)); - cards.add(new SetCardInfo("Atzocan Seer", "153a", Rarity.UNCOMMON, mage.cards.a.AtzocanSeer.class)); + cards.add(new SetCardInfo("Atzal, Cave of Eternity", "160b", Rarity.RARE, mage.cards.a.AtzalCaveOfEternity.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Atzocan Seer", "153", Rarity.UNCOMMON, mage.cards.a.AtzocanSeer.class)); cards.add(new SetCardInfo("Awakened Amalgam", 175, Rarity.RARE, mage.cards.a.AwakenedAmalgam.class)); - cards.add(new SetCardInfo("Azor's Gateway", 176, Rarity.MYTHIC, mage.cards.a.AzorsGateway.class)); + cards.add(new SetCardInfo("Azor's Gateway", "176a", Rarity.MYTHIC, mage.cards.a.AzorsGateway.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Azor, the Lawbringer", 154, Rarity.MYTHIC, mage.cards.a.AzorTheLawbringer.class)); cards.add(new SetCardInfo("Baffling End", 1, Rarity.UNCOMMON, mage.cards.b.BafflingEnd.class)); cards.add(new SetCardInfo("Bishop of Binding", 2, Rarity.RARE, mage.cards.b.BishopOfBinding.class)); @@ -129,11 +131,11 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Gleaming Barrier", 178, Rarity.COMMON, mage.cards.g.GleamingBarrier.class)); cards.add(new SetCardInfo("Goblin Trailblazer", 105, Rarity.COMMON, mage.cards.g.GoblinTrailblazer.class)); cards.add(new SetCardInfo("Golden Demise", 73, Rarity.UNCOMMON, mage.cards.g.GoldenDemise.class)); - cards.add(new SetCardInfo("Golden Guardian", "179a", Rarity.RARE, mage.cards.g.GoldenGuardian.class)); - cards.add(new SetCardInfo("Gold-Forge Garrison", "179b", Rarity.RARE, mage.cards.g.GoldForgeGarrison.class)); + cards.add(new SetCardInfo("Golden Guardian", "179a", Rarity.RARE, mage.cards.g.GoldenGuardian.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Gold-Forge Garrison", "179b", Rarity.RARE, mage.cards.g.GoldForgeGarrison.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grasping Scoundrel", 74, Rarity.COMMON, mage.cards.g.GraspingScoundrel.class)); cards.add(new SetCardInfo("Gruesome Fate", 75, Rarity.COMMON, mage.cards.g.GruesomeFate.class)); - cards.add(new SetCardInfo("Hadana's Climb", "158a", Rarity.RARE, mage.cards.h.HadanasClimb.class)); + cards.add(new SetCardInfo("Hadana's Climb", "158a", Rarity.RARE, mage.cards.h.HadanasClimb.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Hardy Veteran", 132, Rarity.COMMON, mage.cards.h.HardyVeteran.class)); cards.add(new SetCardInfo("Highland Lake", 189, Rarity.UNCOMMON, mage.cards.h.HighlandLake.class)); cards.add(new SetCardInfo("Hornswoggle", 39, Rarity.UNCOMMON, mage.cards.h.Hornswoggle.class)); @@ -146,7 +148,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Jade Bearer", 134, Rarity.COMMON, mage.cards.j.JadeBearer.class)); cards.add(new SetCardInfo("Jadecraft Artisan", 135, Rarity.COMMON, mage.cards.j.JadecraftArtisan.class)); cards.add(new SetCardInfo("Jadelight Ranger", 136, Rarity.RARE, mage.cards.j.JadelightRanger.class)); - cards.add(new SetCardInfo("Journey to Eternity", "160a", Rarity.RARE, mage.cards.j.JourneyToEternity.class)); + cards.add(new SetCardInfo("Journey to Eternity", "160a", Rarity.RARE, mage.cards.j.JourneyToEternity.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jungle Creeper", 161, Rarity.UNCOMMON, mage.cards.j.JungleCreeper.class)); cards.add(new SetCardInfo("Jungleborn Pioneer", 137, Rarity.COMMON, mage.cards.j.JunglebornPioneer.class)); cards.add(new SetCardInfo("Kitesail Corsair", 41, Rarity.COMMON, mage.cards.k.KitesailCorsair.class)); @@ -161,7 +163,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Mastermind's Acquisition", 77, Rarity.RARE, mage.cards.m.MastermindsAcquisition.class)); cards.add(new SetCardInfo("Mausoleum Harpy", 78, Rarity.UNCOMMON, mage.cards.m.MausoleumHarpy.class)); cards.add(new SetCardInfo("Merfolk Mistbinder", 164, Rarity.UNCOMMON, mage.cards.m.MerfolkMistbinder.class)); - cards.add(new SetCardInfo("Metzali, Tower of Triumph", "165b", Rarity.RARE, mage.cards.m.MetzaliTowerOfTriumph.class)); + cards.add(new SetCardInfo("Metzali, Tower of Triumph", "165b", Rarity.RARE, mage.cards.m.MetzaliTowerOfTriumph.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mist-Cloaked Herald", 43, Rarity.COMMON, mage.cards.m.MistCloakedHerald.class)); cards.add(new SetCardInfo("Moment of Craving", 79, Rarity.COMMON, mage.cards.m.MomentOfCraving.class)); cards.add(new SetCardInfo("Moment of Triumph", 15, Rarity.COMMON, mage.cards.m.MomentOfTriumph.class)); @@ -178,19 +180,19 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Overgrown Armasaur", 141, Rarity.COMMON, mage.cards.o.OvergrownArmasaur.class)); cards.add(new SetCardInfo("Paladin of Atonement", 16, Rarity.RARE, mage.cards.p.PaladinOfAtonement.class)); cards.add(new SetCardInfo("Path of Discovery", 142, Rarity.RARE, mage.cards.p.PathOfDiscovery.class)); - cards.add(new SetCardInfo("Path of Mettle", "165a", Rarity.RARE, mage.cards.p.PathOfMettle.class)); + cards.add(new SetCardInfo("Path of Mettle", "165a", Rarity.RARE, mage.cards.p.PathOfMettle.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Pirate's Pillage", 109, Rarity.UNCOMMON, mage.cards.p.PiratesPillage.class)); cards.add(new SetCardInfo("Pitiless Plunderer", 81, Rarity.UNCOMMON, mage.cards.p.PitilessPlunderer.class)); cards.add(new SetCardInfo("Plains", 192, Rarity.COMMON, mage.cards.basiclands.Plains.class)); cards.add(new SetCardInfo("Plummet", 143, Rarity.COMMON, mage.cards.p.Plummet.class)); cards.add(new SetCardInfo("Polyraptor", 144, Rarity.MYTHIC, mage.cards.p.Polyraptor.class)); cards.add(new SetCardInfo("Pride of Conquerors", 17, Rarity.UNCOMMON, mage.cards.p.PrideOfConquerors.class)); - cards.add(new SetCardInfo("Profane Procession", "166a", Rarity.RARE, mage.cards.p.ProfaneProcession.class)); + cards.add(new SetCardInfo("Profane Procession", "166a", Rarity.RARE, mage.cards.p.ProfaneProcession.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Protean Raider", 167, Rarity.RARE, mage.cards.p.ProteanRaider.class)); cards.add(new SetCardInfo("Radiant Destiny", 18, Rarity.RARE, mage.cards.r.RadiantDestiny.class)); cards.add(new SetCardInfo("Raging Regisaur", 168, Rarity.UNCOMMON, mage.cards.r.RagingRegisaur.class)); cards.add(new SetCardInfo("Raptor Companion", 19, Rarity.COMMON, mage.cards.r.RaptorCompanion.class)); - cards.add(new SetCardInfo("Ravenous Chupacabra", 82, Rarity.COMMON, mage.cards.r.RavenousChupacabra.class)); + cards.add(new SetCardInfo("Ravenous Chupacabra", 82, Rarity.UNCOMMON, mage.cards.r.RavenousChupacabra.class)); cards.add(new SetCardInfo("Reaver Ambush", 83, Rarity.UNCOMMON, mage.cards.r.ReaverAmbush.class)); cards.add(new SetCardInfo("Reckless Rage", 110, Rarity.UNCOMMON, mage.cards.r.RecklessRage.class)); cards.add(new SetCardInfo("Recover", 84, Rarity.COMMON, mage.cards.r.Recover.class)); @@ -202,7 +204,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Riverwise Augur", 48, Rarity.UNCOMMON, mage.cards.r.RiverwiseAugur.class)); cards.add(new SetCardInfo("Sadistic Skymarcher", 85, Rarity.UNCOMMON, mage.cards.s.SadisticSkymarcher.class)); cards.add(new SetCardInfo("Sailor of Means", 49, Rarity.COMMON, mage.cards.s.SailorOfMeans.class)); - cards.add(new SetCardInfo("Sanctum of the Sun", "176b", Rarity.MYTHIC, mage.cards.s.SanctumOfTheSun.class)); + cards.add(new SetCardInfo("Sanctum of the Sun", "176b", Rarity.MYTHIC, mage.cards.s.SanctumOfTheSun.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sanguine Glorifier", 20, Rarity.COMMON, mage.cards.s.SanguineGlorifier.class)); cards.add(new SetCardInfo("Sea Legs", 50, Rarity.COMMON, mage.cards.s.SeaLegs.class)); cards.add(new SetCardInfo("Seafloor Oracle", 51, Rarity.RARE, mage.cards.s.SeafloorOracle.class)); @@ -227,7 +229,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Stone Quarry", 190, Rarity.UNCOMMON, mage.cards.s.StoneQuarry.class)); cards.add(new SetCardInfo("Storm Fleet Sprinter", 172, Rarity.UNCOMMON, mage.cards.s.StormFleetSprinter.class)); cards.add(new SetCardInfo("Storm Fleet Swashbuckler", 117, Rarity.UNCOMMON, mage.cards.s.StormFleetSwashbuckler.class)); - cards.add(new SetCardInfo("Storm the Vault", "173a", Rarity.RARE, mage.cards.s.StormTheVault.class)); + cards.add(new SetCardInfo("Storm the Vault", "173a", Rarity.RARE, mage.cards.s.StormTheVault.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Strength of the Pack", 145, Rarity.UNCOMMON, mage.cards.s.StrengthOfThePack.class)); cards.add(new SetCardInfo("Strider Harness", 183, Rarity.COMMON, mage.cards.s.StriderHarness.class)); cards.add(new SetCardInfo("Sun Sentinel", 26, Rarity.COMMON, mage.cards.s.SunSentinel.class)); @@ -247,14 +249,14 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Tilonali's Crown", 120, Rarity.COMMON, mage.cards.t.TilonalisCrown.class)); cards.add(new SetCardInfo("Tilonalli's Summoner", 121, Rarity.RARE, mage.cards.t.TilonallisSummoner.class)); cards.add(new SetCardInfo("Timestream Navigator", 59, Rarity.MYTHIC, mage.cards.t.TimestreamNavigator.class)); - cards.add(new SetCardInfo("Tomb of the Dusk Rose", "166b", Rarity.RARE, mage.cards.t.TombOfTheDuskRose.class)); + cards.add(new SetCardInfo("Tomb of the Dusk Rose", "166b", Rarity.RARE, mage.cards.t.TombOfTheDuskRose.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tomb Robber", 87, Rarity.RARE, mage.cards.t.TombRobber.class)); cards.add(new SetCardInfo("Trapjaw Tyrant", 29, Rarity.MYTHIC, mage.cards.t.TrapjawTyrant.class)); cards.add(new SetCardInfo("Traveler's Amulet", 184, Rarity.COMMON, mage.cards.t.TravelersAmulet.class)); cards.add(new SetCardInfo("Twilight Prophet", 88, Rarity.MYTHIC, mage.cards.t.TwilightProphet.class)); cards.add(new SetCardInfo("Vampire Champion", 198, Rarity.COMMON, mage.cards.v.VampireChampion.class)); cards.add(new SetCardInfo("Vampire Revenant", 89, Rarity.COMMON, mage.cards.v.VampireRevenant.class)); - cards.add(new SetCardInfo("Vault of Catlacan", "173b", Rarity.RARE, mage.cards.v.VaultOfCatlacan.class)); + cards.add(new SetCardInfo("Vault of Catlacan", "173b", Rarity.RARE, mage.cards.v.VaultOfCatlacan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vona's Hunger", 90, Rarity.RARE, mage.cards.v.VonasHunger.class)); cards.add(new SetCardInfo("Voracious Vampire", 91, Rarity.COMMON, mage.cards.v.VoraciousVampire.class)); cards.add(new SetCardInfo("Vraska, Scheming Gorgon", 197, Rarity.MYTHIC, mage.cards.v.VraskaSchemingGorgon.class)); @@ -263,7 +265,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Warkite Marauder", 60, Rarity.RARE, mage.cards.w.WarkiteMarauder.class)); cards.add(new SetCardInfo("Waterknot", 61, Rarity.COMMON, mage.cards.w.Waterknot.class)); cards.add(new SetCardInfo("Wayward Swordtooth", 150, Rarity.RARE, mage.cards.w.WaywardSwordtooth.class)); - cards.add(new SetCardInfo("Winged Temple of Orazca", "158b", Rarity.RARE, mage.cards.w.WingedTempleOfOrazca.class)); + cards.add(new SetCardInfo("Winged Temple of Orazca", "158b", Rarity.RARE, mage.cards.w.WingedTempleOfOrazca.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Woodland Stream", 191, Rarity.UNCOMMON, mage.cards.w.WoodlandStream.class)); cards.add(new SetCardInfo("World Shaper", 151, Rarity.RARE, mage.cards.w.WorldShaper.class)); cards.add(new SetCardInfo("Zacama, Primal Calamity", 174, Rarity.MYTHIC, mage.cards.z.ZacamaPrimalCalamity.class)); From 46bcad2adacaee021e7b367930e54f951ad0934e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 18:04:59 +0100 Subject: [PATCH 18/71] Mage 1.4.26V11 --- Mage.Common/src/main/java/mage/utils/MageVersion.java | 2 +- Mage/src/main/java/mage/cards/repository/CardRepository.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index d034e291559..2b93701ff78 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 26; - public final static String MAGE_VERSION_MINOR_PATCH = "V10"; + public final static String MAGE_VERSION_MINOR_PATCH = "V11"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 96df863e88a..c2107071097 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -58,7 +58,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 51; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 97; + private static final long CARD_CONTENT_VERSION = 98; private Dao cardDao; private Set classNames; @@ -330,7 +330,6 @@ public enum CardRepository { return findPreferedCoreExpansionCard(name, caseInsensitive, null); } - public CardInfo findPreferedCoreExpansionCard(String name, boolean caseInsensitive, String preferedSetCode) { List cards; @@ -348,7 +347,7 @@ public enum CardRepository { ExpansionInfo set = ExpansionRepository.instance.getSetByCode(cardinfo.getSetCode()); if (set != null) { - if ((preferedSetCode != null) && (preferedSetCode.equals(set.getCode()))){ + if ((preferedSetCode != null) && (preferedSetCode.equals(set.getCode()))) { return cardinfo; } From c07e3d327c196e9e0ffc2523a8699db6232e9e72 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Sun, 7 Jan 2018 22:29:37 +0400 Subject: [PATCH 19/71] Fixed wrong images download for two side cards (clean cards*.db and images needed) --- .../plugins/card/images/DownloadPictures.java | 7 ++++- .../plugins/card/utils/CardImageUtils.java | 12 ++++++-- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 30 +++++++++---------- .../src/mage/sets/ShadowsOverInnistrad.java | 4 +-- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 33564618e67..08e350a2137 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -432,7 +432,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab throw new IllegalStateException("Second side card can't have empty name."); } - url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true); + CardInfo secondSideCard = CardRepository.instance.findCard(card.getSecondSideName()); + if (secondSideCard == null){ + throw new IllegalStateException("Can''t find second side card in database: " + card.getSecondSideName()); + } + + url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), secondSideCard.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true); url.setType2(isType2); allCardsUrls.add(url); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java index 5850cbcc3c0..5c98e07d9e9 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java @@ -208,10 +208,16 @@ public final class CardImageUtils { if (card.getUsesVariousArt()) { finalFileName = cardName + '.' + card.getCollectorId() + ".full.jpg"; } else { - int len = card.getCollectorId().length(); - if (Character.isLetter(card.getCollectorId().charAt(len - 1))) { - finalFileName = cardName + card.getCollectorId().charAt(len - 1) + ".full.jpg"; + if (card.getUsesVariousArt()){ + // only various arts can be same name, but different postfixes (a,b,c,d,e) + int len = card.getCollectorId().length(); + if (Character.isLetter(card.getCollectorId().charAt(len - 1))) { + finalFileName = cardName + card.getCollectorId().charAt(len - 1) + ".full.jpg"; + } else { + finalFileName = cardName + prefixType + ".full.jpg"; + } } else { + // normal cards with same names; finalFileName = cardName + prefixType + ".full.jpg"; } } diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 4ec8d0df626..fc3640ab251 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -67,10 +67,10 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Aquatic Incursion", 32, Rarity.UNCOMMON, mage.cards.a.AquaticIncursion.class)); cards.add(new SetCardInfo("Arch of Orazca", 185, Rarity.RARE, mage.cards.a.ArchOfOrazca.class)); cards.add(new SetCardInfo("Arterial Flow", 62, Rarity.UNCOMMON, mage.cards.a.ArterialFlow.class)); - cards.add(new SetCardInfo("Atzal, Cave of Eternity", "160b", Rarity.RARE, mage.cards.a.AtzalCaveOfEternity.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Atzocan Seer", "153", Rarity.UNCOMMON, mage.cards.a.AtzocanSeer.class)); + cards.add(new SetCardInfo("Atzal, Cave of Eternity", "160b", Rarity.RARE, mage.cards.a.AtzalCaveOfEternity.class)); + cards.add(new SetCardInfo("Atzocan Seer", 153, Rarity.UNCOMMON, mage.cards.a.AtzocanSeer.class)); cards.add(new SetCardInfo("Awakened Amalgam", 175, Rarity.RARE, mage.cards.a.AwakenedAmalgam.class)); - cards.add(new SetCardInfo("Azor's Gateway", "176a", Rarity.MYTHIC, mage.cards.a.AzorsGateway.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Azor's Gateway", "176a", Rarity.MYTHIC, mage.cards.a.AzorsGateway.class)); cards.add(new SetCardInfo("Azor, the Lawbringer", 154, Rarity.MYTHIC, mage.cards.a.AzorTheLawbringer.class)); cards.add(new SetCardInfo("Baffling End", 1, Rarity.UNCOMMON, mage.cards.b.BafflingEnd.class)); cards.add(new SetCardInfo("Bishop of Binding", 2, Rarity.RARE, mage.cards.b.BishopOfBinding.class)); @@ -131,11 +131,11 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Gleaming Barrier", 178, Rarity.COMMON, mage.cards.g.GleamingBarrier.class)); cards.add(new SetCardInfo("Goblin Trailblazer", 105, Rarity.COMMON, mage.cards.g.GoblinTrailblazer.class)); cards.add(new SetCardInfo("Golden Demise", 73, Rarity.UNCOMMON, mage.cards.g.GoldenDemise.class)); - cards.add(new SetCardInfo("Golden Guardian", "179a", Rarity.RARE, mage.cards.g.GoldenGuardian.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Gold-Forge Garrison", "179b", Rarity.RARE, mage.cards.g.GoldForgeGarrison.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Golden Guardian", "179a", Rarity.RARE, mage.cards.g.GoldenGuardian.class)); + cards.add(new SetCardInfo("Gold-Forge Garrison", "179b", Rarity.RARE, mage.cards.g.GoldForgeGarrison.class)); cards.add(new SetCardInfo("Grasping Scoundrel", 74, Rarity.COMMON, mage.cards.g.GraspingScoundrel.class)); cards.add(new SetCardInfo("Gruesome Fate", 75, Rarity.COMMON, mage.cards.g.GruesomeFate.class)); - cards.add(new SetCardInfo("Hadana's Climb", "158a", Rarity.RARE, mage.cards.h.HadanasClimb.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Hadana's Climb", "158a", Rarity.RARE, mage.cards.h.HadanasClimb.class)); cards.add(new SetCardInfo("Hardy Veteran", 132, Rarity.COMMON, mage.cards.h.HardyVeteran.class)); cards.add(new SetCardInfo("Highland Lake", 189, Rarity.UNCOMMON, mage.cards.h.HighlandLake.class)); cards.add(new SetCardInfo("Hornswoggle", 39, Rarity.UNCOMMON, mage.cards.h.Hornswoggle.class)); @@ -148,7 +148,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Jade Bearer", 134, Rarity.COMMON, mage.cards.j.JadeBearer.class)); cards.add(new SetCardInfo("Jadecraft Artisan", 135, Rarity.COMMON, mage.cards.j.JadecraftArtisan.class)); cards.add(new SetCardInfo("Jadelight Ranger", 136, Rarity.RARE, mage.cards.j.JadelightRanger.class)); - cards.add(new SetCardInfo("Journey to Eternity", "160a", Rarity.RARE, mage.cards.j.JourneyToEternity.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Journey to Eternity", "160a", Rarity.RARE, mage.cards.j.JourneyToEternity.class)); cards.add(new SetCardInfo("Jungle Creeper", 161, Rarity.UNCOMMON, mage.cards.j.JungleCreeper.class)); cards.add(new SetCardInfo("Jungleborn Pioneer", 137, Rarity.COMMON, mage.cards.j.JunglebornPioneer.class)); cards.add(new SetCardInfo("Kitesail Corsair", 41, Rarity.COMMON, mage.cards.k.KitesailCorsair.class)); @@ -163,7 +163,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Mastermind's Acquisition", 77, Rarity.RARE, mage.cards.m.MastermindsAcquisition.class)); cards.add(new SetCardInfo("Mausoleum Harpy", 78, Rarity.UNCOMMON, mage.cards.m.MausoleumHarpy.class)); cards.add(new SetCardInfo("Merfolk Mistbinder", 164, Rarity.UNCOMMON, mage.cards.m.MerfolkMistbinder.class)); - cards.add(new SetCardInfo("Metzali, Tower of Triumph", "165b", Rarity.RARE, mage.cards.m.MetzaliTowerOfTriumph.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Metzali, Tower of Triumph", "165b", Rarity.RARE, mage.cards.m.MetzaliTowerOfTriumph.class)); cards.add(new SetCardInfo("Mist-Cloaked Herald", 43, Rarity.COMMON, mage.cards.m.MistCloakedHerald.class)); cards.add(new SetCardInfo("Moment of Craving", 79, Rarity.COMMON, mage.cards.m.MomentOfCraving.class)); cards.add(new SetCardInfo("Moment of Triumph", 15, Rarity.COMMON, mage.cards.m.MomentOfTriumph.class)); @@ -180,14 +180,14 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Overgrown Armasaur", 141, Rarity.COMMON, mage.cards.o.OvergrownArmasaur.class)); cards.add(new SetCardInfo("Paladin of Atonement", 16, Rarity.RARE, mage.cards.p.PaladinOfAtonement.class)); cards.add(new SetCardInfo("Path of Discovery", 142, Rarity.RARE, mage.cards.p.PathOfDiscovery.class)); - cards.add(new SetCardInfo("Path of Mettle", "165a", Rarity.RARE, mage.cards.p.PathOfMettle.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Path of Mettle", "165a", Rarity.RARE, mage.cards.p.PathOfMettle.class)); cards.add(new SetCardInfo("Pirate's Pillage", 109, Rarity.UNCOMMON, mage.cards.p.PiratesPillage.class)); cards.add(new SetCardInfo("Pitiless Plunderer", 81, Rarity.UNCOMMON, mage.cards.p.PitilessPlunderer.class)); cards.add(new SetCardInfo("Plains", 192, Rarity.COMMON, mage.cards.basiclands.Plains.class)); cards.add(new SetCardInfo("Plummet", 143, Rarity.COMMON, mage.cards.p.Plummet.class)); cards.add(new SetCardInfo("Polyraptor", 144, Rarity.MYTHIC, mage.cards.p.Polyraptor.class)); cards.add(new SetCardInfo("Pride of Conquerors", 17, Rarity.UNCOMMON, mage.cards.p.PrideOfConquerors.class)); - cards.add(new SetCardInfo("Profane Procession", "166a", Rarity.RARE, mage.cards.p.ProfaneProcession.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Profane Procession", "166a", Rarity.RARE, mage.cards.p.ProfaneProcession.class)); cards.add(new SetCardInfo("Protean Raider", 167, Rarity.RARE, mage.cards.p.ProteanRaider.class)); cards.add(new SetCardInfo("Radiant Destiny", 18, Rarity.RARE, mage.cards.r.RadiantDestiny.class)); cards.add(new SetCardInfo("Raging Regisaur", 168, Rarity.UNCOMMON, mage.cards.r.RagingRegisaur.class)); @@ -204,7 +204,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Riverwise Augur", 48, Rarity.UNCOMMON, mage.cards.r.RiverwiseAugur.class)); cards.add(new SetCardInfo("Sadistic Skymarcher", 85, Rarity.UNCOMMON, mage.cards.s.SadisticSkymarcher.class)); cards.add(new SetCardInfo("Sailor of Means", 49, Rarity.COMMON, mage.cards.s.SailorOfMeans.class)); - cards.add(new SetCardInfo("Sanctum of the Sun", "176b", Rarity.MYTHIC, mage.cards.s.SanctumOfTheSun.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sanctum of the Sun", "176b", Rarity.MYTHIC, mage.cards.s.SanctumOfTheSun.class)); cards.add(new SetCardInfo("Sanguine Glorifier", 20, Rarity.COMMON, mage.cards.s.SanguineGlorifier.class)); cards.add(new SetCardInfo("Sea Legs", 50, Rarity.COMMON, mage.cards.s.SeaLegs.class)); cards.add(new SetCardInfo("Seafloor Oracle", 51, Rarity.RARE, mage.cards.s.SeafloorOracle.class)); @@ -229,7 +229,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Stone Quarry", 190, Rarity.UNCOMMON, mage.cards.s.StoneQuarry.class)); cards.add(new SetCardInfo("Storm Fleet Sprinter", 172, Rarity.UNCOMMON, mage.cards.s.StormFleetSprinter.class)); cards.add(new SetCardInfo("Storm Fleet Swashbuckler", 117, Rarity.UNCOMMON, mage.cards.s.StormFleetSwashbuckler.class)); - cards.add(new SetCardInfo("Storm the Vault", "173a", Rarity.RARE, mage.cards.s.StormTheVault.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Storm the Vault", "173a", Rarity.RARE, mage.cards.s.StormTheVault.class)); cards.add(new SetCardInfo("Strength of the Pack", 145, Rarity.UNCOMMON, mage.cards.s.StrengthOfThePack.class)); cards.add(new SetCardInfo("Strider Harness", 183, Rarity.COMMON, mage.cards.s.StriderHarness.class)); cards.add(new SetCardInfo("Sun Sentinel", 26, Rarity.COMMON, mage.cards.s.SunSentinel.class)); @@ -249,14 +249,14 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Tilonali's Crown", 120, Rarity.COMMON, mage.cards.t.TilonalisCrown.class)); cards.add(new SetCardInfo("Tilonalli's Summoner", 121, Rarity.RARE, mage.cards.t.TilonallisSummoner.class)); cards.add(new SetCardInfo("Timestream Navigator", 59, Rarity.MYTHIC, mage.cards.t.TimestreamNavigator.class)); - cards.add(new SetCardInfo("Tomb of the Dusk Rose", "166b", Rarity.RARE, mage.cards.t.TombOfTheDuskRose.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tomb of the Dusk Rose", "166b", Rarity.RARE, mage.cards.t.TombOfTheDuskRose.class)); cards.add(new SetCardInfo("Tomb Robber", 87, Rarity.RARE, mage.cards.t.TombRobber.class)); cards.add(new SetCardInfo("Trapjaw Tyrant", 29, Rarity.MYTHIC, mage.cards.t.TrapjawTyrant.class)); cards.add(new SetCardInfo("Traveler's Amulet", 184, Rarity.COMMON, mage.cards.t.TravelersAmulet.class)); cards.add(new SetCardInfo("Twilight Prophet", 88, Rarity.MYTHIC, mage.cards.t.TwilightProphet.class)); cards.add(new SetCardInfo("Vampire Champion", 198, Rarity.COMMON, mage.cards.v.VampireChampion.class)); cards.add(new SetCardInfo("Vampire Revenant", 89, Rarity.COMMON, mage.cards.v.VampireRevenant.class)); - cards.add(new SetCardInfo("Vault of Catlacan", "173b", Rarity.RARE, mage.cards.v.VaultOfCatlacan.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Vault of Catlacan", "173b", Rarity.RARE, mage.cards.v.VaultOfCatlacan.class)); cards.add(new SetCardInfo("Vona's Hunger", 90, Rarity.RARE, mage.cards.v.VonasHunger.class)); cards.add(new SetCardInfo("Voracious Vampire", 91, Rarity.COMMON, mage.cards.v.VoraciousVampire.class)); cards.add(new SetCardInfo("Vraska, Scheming Gorgon", 197, Rarity.MYTHIC, mage.cards.v.VraskaSchemingGorgon.class)); @@ -265,7 +265,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Warkite Marauder", 60, Rarity.RARE, mage.cards.w.WarkiteMarauder.class)); cards.add(new SetCardInfo("Waterknot", 61, Rarity.COMMON, mage.cards.w.Waterknot.class)); cards.add(new SetCardInfo("Wayward Swordtooth", 150, Rarity.RARE, mage.cards.w.WaywardSwordtooth.class)); - cards.add(new SetCardInfo("Winged Temple of Orazca", "158b", Rarity.RARE, mage.cards.w.WingedTempleOfOrazca.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Winged Temple of Orazca", "158b", Rarity.RARE, mage.cards.w.WingedTempleOfOrazca.class)); cards.add(new SetCardInfo("Woodland Stream", 191, Rarity.UNCOMMON, mage.cards.w.WoodlandStream.class)); cards.add(new SetCardInfo("World Shaper", 151, Rarity.RARE, mage.cards.w.WorldShaper.class)); cards.add(new SetCardInfo("Zacama, Primal Calamity", 174, Rarity.MYTHIC, mage.cards.z.ZacamaPrimalCalamity.class)); diff --git a/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java b/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java index 007db00f556..fd811f4834d 100644 --- a/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java +++ b/Mage.Sets/src/mage/sets/ShadowsOverInnistrad.java @@ -136,7 +136,7 @@ public class ShadowsOverInnistrad extends ExpansionSet { cards.add(new SetCardInfo("Dual Shot", 153, Rarity.COMMON, mage.cards.d.DualShot.class)); cards.add(new SetCardInfo("Duskwatch Recruiter", 203, Rarity.UNCOMMON, mage.cards.d.DuskwatchRecruiter.class)); cards.add(new SetCardInfo("Eerie Interlude", 16, Rarity.RARE, mage.cards.e.EerieInterlude.class)); - cards.add(new SetCardInfo("Elusive Tormentor", 108, Rarity.RARE, mage.cards.e.ElusiveTormentor.class)); + cards.add(new SetCardInfo("Elusive Tormentor", "108a", Rarity.RARE, mage.cards.e.ElusiveTormentor.class)); cards.add(new SetCardInfo("Ember-Eye Wolf", 154, Rarity.COMMON, mage.cards.e.EmberEyeWolf.class)); cards.add(new SetCardInfo("Emissary of the Sleepless", 17, Rarity.COMMON, mage.cards.e.EmissaryOfTheSleepless.class)); cards.add(new SetCardInfo("Engulf the Shore", 58, Rarity.RARE, mage.cards.e.EngulfTheShore.class)); @@ -207,7 +207,7 @@ public class ShadowsOverInnistrad extends ExpansionSet { cards.add(new SetCardInfo("Infectious Curse", 97, Rarity.UNCOMMON, mage.cards.i.InfectiousCurse.class)); cards.add(new SetCardInfo("Inner Struggle", 167, Rarity.UNCOMMON, mage.cards.i.InnerStruggle.class)); cards.add(new SetCardInfo("Inquisitor's Ox", 24, Rarity.COMMON, mage.cards.i.InquisitorsOx.class)); - cards.add(new SetCardInfo("Insidious Mist", 108, Rarity.RARE, mage.cards.i.InsidiousMist.class)); + cards.add(new SetCardInfo("Insidious Mist", "108b", Rarity.RARE, mage.cards.i.InsidiousMist.class)); cards.add(new SetCardInfo("Insolent Neonate", 168, Rarity.COMMON, mage.cards.i.InsolentNeonate.class)); cards.add(new SetCardInfo("Inspiring Captain", 25, Rarity.COMMON, mage.cards.i.InspiringCaptain.class)); cards.add(new SetCardInfo("Intrepid Provisioner", 213, Rarity.COMMON, mage.cards.i.IntrepidProvisioner.class)); From 47fc1b5845cc7100eb6495423d4e702a0d21ca6c Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 00:35:06 +0400 Subject: [PATCH 20/71] [RIX] Kumena, Tyrant of Orazca - fixed than it place counter to all cards instead merfolk --- Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java b/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java index 6e2c7d575d8..f55f34297b9 100644 --- a/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java +++ b/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java @@ -67,7 +67,7 @@ public class KumenaTyrantOfOrazca extends CardImpl { filter.add(new SubtypePredicate(SubType.MERFOLK)); filter.add(Predicates.not(new TappedPredicate())); - filter.add(new SubtypePredicate(SubType.MERFOLK)); + filterAll.add(new SubtypePredicate(SubType.MERFOLK)); } public KumenaTyrantOfOrazca(UUID ownerId, CardSetInfo setInfo) { @@ -92,7 +92,7 @@ public class KumenaTyrantOfOrazca extends CardImpl { // Tap five untapped Merfolk you control: Put a +1/+1 counter on each Merfolk you control. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(), filterAll), - new TapTargetCost(new TargetControlledPermanent(5, 5, filter, true)))); + new TapTargetCost(new TargetControlledPermanent(5, 5, filterAll, true)))); } From 2564f611823ad60526fcc0dd22ea222385f1305f Mon Sep 17 00:00:00 2001 From: igoudt Date: Sun, 7 Jan 2018 21:47:00 +0100 Subject: [PATCH 21/71] HumanPlayer constructor missed a reference to attribute --- .../Mage.Player.Human/src/mage/player/human/HumanPlayer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 2218b7bf1aa..96628efb215 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -121,7 +121,7 @@ public class HumanPlayer extends PlayerImpl { public HumanPlayer(final HumanPlayer player) { super(player); this.replacementEffectChoice = player.replacementEffectChoice; - this.autoSelectReplacementEffects.addAll(autoSelectReplacementEffects); + this.autoSelectReplacementEffects.addAll(player.autoSelectReplacementEffects); this.currentlyUnpaidMana = player.currentlyUnpaidMana; this.triggerAutoOrderAbilityFirst.addAll(player.triggerAutoOrderAbilityFirst); From 13c8627bf196f9a25c978e45e863e474d35ff1d1 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 00:49:24 +0400 Subject: [PATCH 22/71] [RIX] Kumena, Tyrant of Orazca - full fix --- .../mage/cards/k/KumenaTyrantOfOrazca.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java b/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java index f55f34297b9..e01e24b0ea4 100644 --- a/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java +++ b/Mage.Sets/src/mage/cards/k/KumenaTyrantOfOrazca.java @@ -55,17 +55,17 @@ import mage.target.common.TargetControlledPermanent; */ public class KumenaTyrantOfOrazca extends CardImpl { - private static final FilterControlledPermanent filterAnother = new FilterControlledPermanent("another untapped Merfolk you control"); - private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Merfolk you control"); + private static final FilterControlledPermanent filterAnotherNotTapped = new FilterControlledPermanent("another untapped Merfolk you control"); + private static final FilterControlledPermanent filterNotTapped = new FilterControlledPermanent("untapped Merfolk you control"); private static final FilterControlledPermanent filterAll = new FilterControlledPermanent("Merfolk you control"); static { - filterAnother.add(new AnotherPredicate()); - filterAnother.add(new SubtypePredicate(SubType.MERFOLK)); - filterAnother.add(Predicates.not(new TappedPredicate())); + filterAnotherNotTapped.add(new AnotherPredicate()); + filterAnotherNotTapped.add(new SubtypePredicate(SubType.MERFOLK)); + filterAnotherNotTapped.add(Predicates.not(new TappedPredicate())); - filter.add(new SubtypePredicate(SubType.MERFOLK)); - filter.add(Predicates.not(new TappedPredicate())); + filterNotTapped.add(new SubtypePredicate(SubType.MERFOLK)); + filterNotTapped.add(Predicates.not(new TappedPredicate())); filterAll.add(new SubtypePredicate(SubType.MERFOLK)); } @@ -82,17 +82,17 @@ public class KumenaTyrantOfOrazca extends CardImpl { // Tap another untapped Merfolk you control: Kumena, Tyrant of Orzca can't be blocked this turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedSourceEffect(Duration.EndOfTurn), - new TapTargetCost(new TargetControlledPermanent(1, 1, filterAnother, true)))); + new TapTargetCost(new TargetControlledPermanent(1, 1, filterAnotherNotTapped, true)))); // Tap three untapped Merfolk you control: Draw a card. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new TapTargetCost(new TargetControlledPermanent(3, 3, filter, true)))); + new TapTargetCost(new TargetControlledPermanent(3, 3, filterNotTapped, true)))); // Tap five untapped Merfolk you control: Put a +1/+1 counter on each Merfolk you control. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(), filterAll), - new TapTargetCost(new TargetControlledPermanent(5, 5, filterAll, true)))); + new TapTargetCost(new TargetControlledPermanent(5, 5, filterNotTapped, true)))); } From 995c58e38197baaa100837f0833e8fab23041a42 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 22:11:12 +0100 Subject: [PATCH 23/71] * Reckless Rage - Fixed damge dealing to the creatures. --- Mage.Sets/src/mage/cards/r/RecklessRage.java | 91 +++---------------- .../effects/common/DamageTargetEffect.java | 11 ++- 2 files changed, 20 insertions(+), 82 deletions(-) diff --git a/Mage.Sets/src/mage/cards/r/RecklessRage.java b/Mage.Sets/src/mage/cards/r/RecklessRage.java index 9e7313ea466..23e9d394e49 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessRage.java +++ b/Mage.Sets/src/mage/cards/r/RecklessRage.java @@ -27,42 +27,16 @@ */ package mage.cards.r; -import java.io.ObjectStreamException; import java.util.UUID; - -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.common.RaidCondition; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.costs.mana.VariableManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.EntersBattlefieldEffect; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.*; -import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.permanent.token.WingmateRocToken; -import mage.players.Player; -import mage.target.Target; -import mage.target.TargetPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetOpponentsCreaturePermanent; -import mage.watchers.common.PlayerAttackedWatcher; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; /** * @author JayDi85 @@ -73,9 +47,14 @@ public class RecklessRage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Reckless Rage deals 4 damage to target creature you don’t control and 2 damage to target creature you control. - this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent()); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don’t control"); + filter.add(new ControllerPredicate(TargetController.NOT_YOU)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new DamageTargetEffect(4).setUseOnlyTargetPointer(true)); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addEffect(RecklessRageEffect.getInstance()); + this.getSpellAbility().addEffect(new DamageTargetEffect(2).setUseOnlyTargetPointer(true) + .setText("and 2 damage to target creature you control") + .setTargetPointer(new SecondTargetPointer())); } public RecklessRage(final RecklessRage card) { @@ -87,49 +66,3 @@ public class RecklessRage extends CardImpl { return new RecklessRage(this); } } - -class RecklessRageEffect extends OneShotEffect { - - private static final RecklessRageEffect instance = new RecklessRageEffect(); - - private Object readResolve() throws ObjectStreamException { - return instance; - } - - public static RecklessRageEffect getInstance() { - return instance; - } - - private RecklessRageEffect ( ) { - super(Outcome.Damage); - staticText = "{source} deals 4 damage to target creature you don’t control and 2 damage to target creature you control."; - } - - @Override - public boolean apply(Game game, Ability source) { - - boolean completed = false; - int stepNumber = 1; - - for ( Target target : source.getTargets() ) { - if (stepNumber > 2) { - System.out.println("ERROR: " + RecklessRage.class.toString() + " got too many targets (need 2, got " + source.getTargets().size() + ")"); - break; - } - - Permanent permanent = game.getPermanent(target.getFirstTarget()); - - if(permanent != null){ - completed |= (permanent.damage( (stepNumber == 1) ? 2 : 4, source.getSourceId(), game, false, true ) > 0); - } - - stepNumber = stepNumber + 1; - } - return completed; - } - - @Override - public Effect copy() { - return instance; - } -} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java index 97e9e45c7e0..2ba553547d5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java @@ -27,10 +27,12 @@ */ package mage.abilities.effects.common; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; @@ -38,8 +40,6 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com @@ -129,6 +129,11 @@ public class DamageTargetEffect extends OneShotEffect { this.sourceName = sourceName; } + public Effect setUseOnlyTargetPointer(boolean useOnlyTargetPointer) { + this.useOnlyTargetPointer = useOnlyTargetPointer; + return this; + } + @Override public DamageTargetEffect copy() { return new DamageTargetEffect(this); @@ -152,7 +157,7 @@ public class DamageTargetEffect extends OneShotEffect { } return true; } - for (UUID targetId :this.getTargetPointer().getTargets(game, source)) { + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { permanent.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, preventable); From 8b35f38efab684a56b86c161d1e3416e94839a27 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 22:11:59 +0100 Subject: [PATCH 24/71] * Warkite Marauder - Fixed wrong defender target handling (fixes #4354). --- .../src/mage/cards/w/WarkiteMarauder.java | 198 +++++++++--------- 1 file changed, 98 insertions(+), 100 deletions(-) diff --git a/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java b/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java index 927440b9fab..6f735bd42bd 100644 --- a/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java +++ b/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java @@ -1,100 +1,98 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.cards.w; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.effects.common.continuous.LoseAllAbilitiesTargetEffect; -import mage.abilities.effects.common.continuous.SetPowerToughnessTargetEffect; -import mage.abilities.keyword.FlyingAbility; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; - -/** - * - * @author LevelX2 - */ -public class WarkiteMarauder extends CardImpl { - - private final UUID originalId; - - public WarkiteMarauder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); - - this.subtype.add(SubType.HUMAN); - this.subtype.add(SubType.PIRATE); - this.power = new MageInt(2); - this.toughness = new MageInt(1); - - // Flying - this.addAbility(FlyingAbility.getInstance()); - - // Whenever Warkite Marauder attacks, target creature defending player controls loses all abilities and has base power and toughness 0/1 until end of turn. - Ability ability = new AttacksTriggeredAbility(new LoseAllAbilitiesTargetEffect(Duration.EndOfTurn) - .setText("target creature defending player controls loses all abilities"), false); - ability.addEffect(new SetPowerToughnessTargetEffect(0, 1, Duration.EndOfTurn) - .setText("and has base power and toughness 0/1 until end of turn")); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); - this.addAbility(ability); - this.originalId = ability.getOriginalId(); - - } - - public WarkiteMarauder(final WarkiteMarauder card) { - super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - ability.getTargets().clear(); - ability.addTarget(new TargetControlledCreaturePermanent()); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - ability.addTarget(target); - } - } - - @Override - public WarkiteMarauder copy() { - return new WarkiteMarauder(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.w; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.continuous.LoseAllAbilitiesTargetEffect; +import mage.abilities.effects.common.continuous.SetPowerToughnessTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class WarkiteMarauder extends CardImpl { + + private final UUID originalId; + + public WarkiteMarauder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PIRATE); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever Warkite Marauder attacks, target creature defending player controls loses all abilities and has base power and toughness 0/1 until end of turn. + Ability ability = new AttacksTriggeredAbility(new LoseAllAbilitiesTargetEffect(Duration.EndOfTurn) + .setText("target creature defending player controls loses all abilities"), false); + ability.addEffect(new SetPowerToughnessTargetEffect(0, 1, Duration.EndOfTurn) + .setText("and has base power and toughness 0/1 until end of turn")); + ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + this.addAbility(ability); + this.originalId = ability.getOriginalId(); + + } + + public WarkiteMarauder(final WarkiteMarauder card) { + super(card); + this.originalId = card.originalId; + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability.getOriginalId().equals(originalId)) { + ability.getTargets().clear(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); + UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId()); + filter.add(new ControllerIdPredicate(defenderId)); + TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, false); + ability.addTarget(target); + } + } + + @Override + public WarkiteMarauder copy() { + return new WarkiteMarauder(this); + } +} From 423e3847a8b20b59c5d8d2dba75648bf7dd7e967 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 22:19:46 +0100 Subject: [PATCH 25/71] * Oathsworn Vampire - Fixed a possible exception bug. --- Mage.Sets/src/mage/cards/o/OathswornVampire.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/o/OathswornVampire.java b/Mage.Sets/src/mage/cards/o/OathswornVampire.java index 69eaa5f4431..0489e1449d7 100644 --- a/Mage.Sets/src/mage/cards/o/OathswornVampire.java +++ b/Mage.Sets/src/mage/cards/o/OathswornVampire.java @@ -91,6 +91,7 @@ class OathswornVampirePlayEffect extends AsThoughEffectImpl { public OathswornVampirePlayEffect(final OathswornVampirePlayEffect effect) { super(effect); + this.condition = effect.condition; } @Override From 6de177f8ac236aba1b285b0e8e3a39187778a3e9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 22:23:41 +0100 Subject: [PATCH 26/71] * Order of Succession - Fixed possible exception error. --- Mage.Sets/src/mage/cards/o/OrderOfSuccession.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java b/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java index 4bfa6ea3574..fa5a5d8d062 100644 --- a/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java +++ b/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java @@ -58,8 +58,7 @@ import mage.target.targetpointer.FixedTarget; public class OrderOfSuccession extends CardImpl { public OrderOfSuccession(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}"); // Choose left or right. Starting with you and proceeding in the chosen direction, each player chooses a creature controlled by the next player in that direction. Each player gains control of the creature he or she chose. this.getSpellAbility().addEffect(new OrderOfSuccessionEffect()); @@ -98,7 +97,7 @@ class OrderOfSuccessionEffect extends OneShotEffect { Map playerCreature = new HashMap<>(2); Choice choice = new ChoiceLeftOrRight(); controller.choose(Outcome.Neutral, choice, game); - boolean left = choice.getChoice().equals("Left"); + boolean left = choice == null || choice.getChoice().equals("Left"); // to prevent npe PlayerList playerList = game.getState().getPlayerList().copy(); // set playerlist to controller while (!playerList.get().equals(source.getControllerId()) && controller.canRespond()) { @@ -108,7 +107,7 @@ class OrderOfSuccessionEffect extends OneShotEffect { Player nextPlayer; UUID firstNextPlayer = null; - while (!getNextPlayerInDirection(left, playerList, game).equals(firstNextPlayer) && controller.canRespond()){ + while (!getNextPlayerInDirection(left, playerList, game).equals(firstNextPlayer) && controller.canRespond()) { nextPlayer = game.getPlayer(playerList.get()); if (nextPlayer == null) { return false; From 6d16e41ec307c1108821ab45ea6f891c20f1f274 Mon Sep 17 00:00:00 2001 From: igoudt Date: Sun, 7 Jan 2018 22:38:54 +0100 Subject: [PATCH 27/71] use some staticfilters, rewrite some lines to java8 streams --- Mage.Sets/src/mage/cards/a/AvoidFate.java | 7 +++--- .../src/mage/cards/c/CurseOfTheCabal.java | 23 +++++++++---------- .../src/mage/cards/m/MakeshiftMunitions.java | 16 ++++--------- .../keyword/AffinityForArtifactsAbility.java | 13 +++-------- .../abilities/keyword/AnnihilatorAbility.java | 22 ++++++++---------- .../mage/filter/predicate/Predicates.java | 15 +++--------- .../game/command/emblems/DovinBaanEmblem.java | 4 ++-- 7 files changed, 37 insertions(+), 63 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AvoidFate.java b/Mage.Sets/src/mage/cards/a/AvoidFate.java index ace9a59fb63..21c02c3ff97 100644 --- a/Mage.Sets/src/mage/cards/a/AvoidFate.java +++ b/Mage.Sets/src/mage/cards/a/AvoidFate.java @@ -27,20 +27,21 @@ */ package mage.cards.a; -import java.util.UUID; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.FilterSpell; -import mage.filter.common.FilterControlledPermanent; +import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.other.TargetsPermanentPredicate; import mage.target.TargetSpell; +import java.util.UUID; + /** * * @author LoneFox @@ -51,7 +52,7 @@ public class AvoidFate extends CardImpl { static { filter.add(Predicates.or(new CardTypePredicate(CardType.INSTANT), new SubtypePredicate(SubType.AURA))); - filter.add(new TargetsPermanentPredicate(new FilterControlledPermanent())); + filter.add(new TargetsPermanentPredicate(StaticFilters.FILTER_CONTROLLED_PERMANENT)); } public AvoidFate(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java index 9b36bf77d95..6ec8aa4ea76 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java @@ -27,7 +27,6 @@ */ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.SuspendedCondition; @@ -46,14 +45,17 @@ import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.TargetPlayer; import mage.target.common.TargetControlledPermanent; +import java.util.Objects; +import java.util.UUID; + /** * * @author anonymous @@ -84,8 +86,6 @@ public class CurseOfTheCabal extends CardImpl { class CurseOfTheCabalSacrificeEffect extends OneShotEffect { - private static final FilterControlledPermanent FILTER = new FilterControlledPermanent(); // ggf filter.FilterPermanent - public CurseOfTheCabalSacrificeEffect() { super(Outcome.Sacrifice); this.staticText = "Target player sacrifices half the permanents he or she controls, rounded down."; @@ -104,21 +104,20 @@ class CurseOfTheCabalSacrificeEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(source.getFirstTarget()); if (targetPlayer != null) { - int amount = game.getBattlefield().countAll(FILTER, targetPlayer.getId(), game) / 2; + int amount = game.getBattlefield().countAll(StaticFilters.FILTER_CONTROLLED_PERMANENT, targetPlayer.getId(), game) / 2; if (amount < 1) { return true; } - Target target = new TargetControlledPermanent(amount, amount, FILTER, true); + Target target = new TargetControlledPermanent(amount, amount, StaticFilters.FILTER_CONTROLLED_PERMANENT, true); if (target.canChoose(targetPlayer.getId(), game)) { while (!target.isChosen() && target.canChoose(targetPlayer.getId(), game) && targetPlayer.canRespond()) { targetPlayer.choose(Outcome.Sacrifice, target, source.getSourceId(), game); } - for (int idx = 0; idx < target.getTargets().size(); idx++) { - Permanent permanent = game.getPermanent(target.getTargets().get(idx)); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - } + //sacrifice all chosen (non null) permanents + target.getTargets().stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .forEach(permanent -> permanent.sacrifice(source.getSourceId(), game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/m/MakeshiftMunitions.java b/Mage.Sets/src/mage/cards/m/MakeshiftMunitions.java index 2be6c83d59d..fa00aa89c22 100644 --- a/Mage.Sets/src/mage/cards/m/MakeshiftMunitions.java +++ b/Mage.Sets/src/mage/cards/m/MakeshiftMunitions.java @@ -27,7 +27,6 @@ */ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; @@ -37,26 +36,19 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreatureOrPlayer; +import java.util.UUID; + /** * * @author TheElk801 */ public class MakeshiftMunitions extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact or creature"); - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.ARTIFACT), - new CardTypePredicate(CardType.CREATURE) - )); - } public MakeshiftMunitions(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); @@ -65,7 +57,7 @@ public class MakeshiftMunitions extends CardImpl { Ability ability = new SimpleActivatedAbility( Zone.BATTLEFIELD, new DamageTargetEffect(1), - new SacrificeTargetCost(new TargetControlledPermanent(filter)) + new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT_OR_CREATURE)) ); ability.addTarget(new TargetCreatureOrPlayer()); ability.addCost(new GenericManaCost(1)); diff --git a/Mage/src/main/java/mage/abilities/keyword/AffinityForArtifactsAbility.java b/Mage/src/main/java/mage/abilities/keyword/AffinityForArtifactsAbility.java index 071a791e1da..b27b1308aa3 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AffinityForArtifactsAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AffinityForArtifactsAbility.java @@ -32,10 +32,8 @@ import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.AdjustingSourceCosts; import mage.abilities.effects.common.AffinityEffect; -import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.util.CardUtil; @@ -43,14 +41,9 @@ import mage.util.CardUtil; * Affinity for artifacts */ public class AffinityForArtifactsAbility extends SimpleStaticAbility implements AdjustingSourceCosts { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(new CardTypePredicate(CardType.ARTIFACT)); - } public AffinityForArtifactsAbility() { - super(Zone.OUTSIDE, new AffinityEffect(filter)); + super(Zone.OUTSIDE, new AffinityEffect(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)); setRuleAtTheTop(true); } @@ -71,7 +64,7 @@ public class AffinityForArtifactsAbility extends SimpleStaticAbility implements @Override public void adjustCosts(Ability ability, Game game) { if (ability instanceof SpellAbility) { - int count = game.getBattlefield().getAllActivePermanents(filter, ability.getControllerId(), game).size(); + int count = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, ability.getControllerId(), game).size(); if (count > 0) { CardUtil.adjustCost((SpellAbility)ability, count); } diff --git a/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java b/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java index d2036ef91a4..735641adc5c 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AnnihilatorAbility.java @@ -27,22 +27,23 @@ */ package mage.abilities.keyword; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.common.FilterControlledPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetControlledPermanent; import mage.util.CardUtil; +import java.util.Objects; +import java.util.UUID; + /** * 702.84. Annihilator 702.84a Annihilator is a triggered ability. "Annihilator * N" means "Whenever this creature attacks, defending player sacrifices N @@ -103,7 +104,6 @@ public class AnnihilatorAbility extends TriggeredAbilityImpl { class AnnihilatorEffect extends OneShotEffect { private final int count; - private static final FilterControlledPermanent FILTER = new FilterControlledPermanent(); AnnihilatorEffect(int count) { super(Outcome.Sacrifice); @@ -123,21 +123,19 @@ class AnnihilatorEffect extends OneShotEffect { player = game.getPlayer(defendingPlayerId); } if (player != null) { - int amount = Math.min(count, game.getBattlefield().countAll(FILTER, player.getId(), game)); + int amount = Math.min(count, game.getBattlefield().countAll(StaticFilters.FILTER_CONTROLLED_PERMANENT, player.getId(), game)); if (amount > 0) { - Target target = new TargetControlledPermanent(amount, amount, FILTER, true); + Target target = new TargetControlledPermanent(amount, amount, StaticFilters.FILTER_CONTROLLED_PERMANENT, true); if (target.canChoose(player.getId(), game)) { while (player.canRespond() && target.canChoose(player.getId(), game) && !target.isChosen()) { player.choose(Outcome.Sacrifice, target, source.getSourceId(), game); } - for (int idx = 0; idx < target.getTargets().size(); idx++) { - Permanent permanent = game.getPermanent(target.getTargets().get(idx)); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - } + target.getTargets().stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .forEach(permanent -> permanent.sacrifice(source.getSourceId(), game)); } return true; } diff --git a/Mage/src/main/java/mage/filter/predicate/Predicates.java b/Mage/src/main/java/mage/filter/predicate/Predicates.java index c37eaa16276..20037f11de7 100644 --- a/Mage/src/main/java/mage/filter/predicate/Predicates.java +++ b/Mage/src/main/java/mage/filter/predicate/Predicates.java @@ -168,12 +168,8 @@ public final class Predicates { @Override public boolean apply(T t, Game game) { - for (Predicate component : components) { - if (!component.apply(t, game)) { - return false; - } - } - return true; + return components.stream().allMatch(predicate -> predicate.apply(t, game)); + } @Override @@ -196,12 +192,7 @@ public final class Predicates { @Override public boolean apply(T t, Game game) { - for (Predicate component : components) { - if (component.apply(t, game)) { - return true; - } - } - return false; + return components.stream().anyMatch(predicate -> predicate.apply(t, game)); } @Override diff --git a/Mage/src/main/java/mage/game/command/emblems/DovinBaanEmblem.java b/Mage/src/main/java/mage/game/command/emblems/DovinBaanEmblem.java index 6df0e451c2f..4855064529a 100644 --- a/Mage/src/main/java/mage/game/command/emblems/DovinBaanEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/DovinBaanEmblem.java @@ -32,7 +32,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.RestrictionUntapNotMoreThanEffect; import mage.constants.Duration; import mage.constants.Zone; -import mage.filter.common.FilterControlledPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.command.Emblem; import mage.players.Player; @@ -53,7 +53,7 @@ public class DovinBaanEmblem extends Emblem { class DovinBaanCantUntapEffect extends RestrictionUntapNotMoreThanEffect { DovinBaanCantUntapEffect() { - super(Duration.WhileOnBattlefield, 2, new FilterControlledPermanent()); + super(Duration.WhileOnBattlefield, 2, StaticFilters.FILTER_CONTROLLED_PERMANENT); staticText = "Your opponents can't untap more than two permanents during their untap steps."; } From 27ec3431ee1bae401885ec0d349567830af90b54 Mon Sep 17 00:00:00 2001 From: igoudt Date: Sun, 7 Jan 2018 22:39:31 +0100 Subject: [PATCH 28/71] rewrite with staticfilter --- .../java/mage/target/common/TargetControlledPermanent.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java b/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java index 5a21d533193..4e38039f535 100644 --- a/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetControlledPermanent.java @@ -28,6 +28,7 @@ package mage.target.common; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; @@ -38,11 +39,11 @@ import mage.target.TargetPermanent; public class TargetControlledPermanent extends TargetPermanent { public TargetControlledPermanent() { - this(1, 1, new FilterControlledPermanent(), false); + this(1, 1, StaticFilters.FILTER_CONTROLLED_PERMANENT, false); } public TargetControlledPermanent(int numTargets) { - this(numTargets, numTargets, new FilterControlledPermanent(), false); + this(numTargets, numTargets, StaticFilters.FILTER_CONTROLLED_PERMANENT, false); } public TargetControlledPermanent(FilterControlledPermanent filter) { From cd437ce8b8b5a416c5cc1342ec7d9aee3cd960c1 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 01:51:49 +0400 Subject: [PATCH 29/71] * Raging Regisaur - Fixed wrong stats and text (see #4358) --- Mage.Sets/src/mage/cards/r/RagingRegisaur.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/r/RagingRegisaur.java b/Mage.Sets/src/mage/cards/r/RagingRegisaur.java index 551a9986e64..261813a8642 100644 --- a/Mage.Sets/src/mage/cards/r/RagingRegisaur.java +++ b/Mage.Sets/src/mage/cards/r/RagingRegisaur.java @@ -47,11 +47,11 @@ public class RagingRegisaur extends CardImpl { public RagingRegisaur(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); this.subtype.add(SubType.DINOSAUR); - this.power = new MageInt(2); - this.toughness = new MageInt(2); + this.power = new MageInt(4); + this.toughness = new MageInt(4); // Whenever Raging Regisaur attacks, it deals 1 damage to target creature or player. - Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(1), false, "it deals 1 damage to target creature or player"); + Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(1, "it"), false); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); } From f81487541095f53a44b7f1cadfe96e9b279af98b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 7 Jan 2018 22:56:48 +0100 Subject: [PATCH 30/71] Xmage 1.4.26V11b --- Mage.Common/src/main/java/mage/utils/MageVersion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index 2b93701ff78..26dd9ca6d3a 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 26; - public final static String MAGE_VERSION_MINOR_PATCH = "V11"; + public final static String MAGE_VERSION_MINOR_PATCH = "V11b"; public final static String MAGE_VERSION_INFO = ""; private final int major; From eb7166aa2fbc113c09914676f80a64daca84fa34 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 09:57:09 +0400 Subject: [PATCH 31/71] * Pirate's Pillage - Fixed wrong random discard (see #4365) --- Mage.Sets/src/mage/cards/p/PiratesPillage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/p/PiratesPillage.java b/Mage.Sets/src/mage/cards/p/PiratesPillage.java index 294f37a42d4..6e2373502da 100644 --- a/Mage.Sets/src/mage/cards/p/PiratesPillage.java +++ b/Mage.Sets/src/mage/cards/p/PiratesPillage.java @@ -46,7 +46,7 @@ public class PiratesPillage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // As an additional cost to cast Pirate's Pillage, discard a card. - this.getSpellAbility().addCost(new DiscardCardCost(true)); + this.getSpellAbility().addCost(new DiscardCardCost(false)); // Draw two cards and create two colorless Treasure artifacts with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool." this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); From daf95cda51804afd7fe757e2dd09626af53be02d Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 10:14:00 +0400 Subject: [PATCH 32/71] * Release to the Wind - Fixed wrong card name Return to the Wind --- ...rnToTheWind.java => ReleaseToTheWind.java} | 34 +++++++++---------- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 5 ++- 2 files changed, 19 insertions(+), 20 deletions(-) rename Mage.Sets/src/mage/cards/r/{ReturnToTheWind.java => ReleaseToTheWind.java} (82%) diff --git a/Mage.Sets/src/mage/cards/r/ReturnToTheWind.java b/Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java similarity index 82% rename from Mage.Sets/src/mage/cards/r/ReturnToTheWind.java rename to Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java index e17f2e5a8dd..858c917cd99 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnToTheWind.java +++ b/Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java @@ -50,41 +50,41 @@ import mage.target.targetpointer.FixedTarget; * * @author LevelX2 */ -public class ReturnToTheWind extends CardImpl { +public class ReleaseToTheWind extends CardImpl { - public ReturnToTheWind(UUID ownerId, CardSetInfo setInfo) { + public ReleaseToTheWind(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Exile target nonland permanent. For as long as that card remains exiled, its owner may cast it without paying its mana cost. - getSpellAbility().addEffect(new ReturnToTheWindEffect()); + getSpellAbility().addEffect(new ReleaseToTheWindEffect()); getSpellAbility().addTarget(new TargetNonlandPermanent()); } - public ReturnToTheWind(final ReturnToTheWind card) { + public ReleaseToTheWind(final ReleaseToTheWind card) { super(card); } @Override - public ReturnToTheWind copy() { - return new ReturnToTheWind(this); + public ReleaseToTheWind copy() { + return new ReleaseToTheWind(this); } } -class ReturnToTheWindEffect extends OneShotEffect { +class ReleaseToTheWindEffect extends OneShotEffect { - public ReturnToTheWindEffect() { + public ReleaseToTheWindEffect() { super(Outcome.Benefit); this.staticText = "Exile target nonland permanent. For as long as that card remains exiled, its owner may cast it without paying its mana cost"; } - public ReturnToTheWindEffect(final ReturnToTheWindEffect effect) { + public ReleaseToTheWindEffect(final ReleaseToTheWindEffect effect) { super(effect); } @Override - public ReturnToTheWindEffect copy() { - return new ReturnToTheWindEffect(this); + public ReleaseToTheWindEffect copy() { + return new ReleaseToTheWindEffect(this); } @Override @@ -96,7 +96,7 @@ class ReturnToTheWindEffect extends OneShotEffect { if (controller.moveCards(targetPermanent, Zone.EXILED, source, game)) { Card card = game.getCard(targetPermanent.getId()); if (card != null) { - ContinuousEffect effect = new ReturnToTheWindEffectCastFromExileEffect(); + ContinuousEffect effect = new ReleaseToTheWindEffectCastFromExileEffect(); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); game.addEffect(effect, source); } @@ -108,14 +108,14 @@ class ReturnToTheWindEffect extends OneShotEffect { } } -class ReturnToTheWindEffectCastFromExileEffect extends AsThoughEffectImpl { +class ReleaseToTheWindEffectCastFromExileEffect extends AsThoughEffectImpl { - public ReturnToTheWindEffectCastFromExileEffect() { + public ReleaseToTheWindEffectCastFromExileEffect() { super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit); staticText = "For as long as that card remains exiled, its owner may cast it without paying its mana cost"; } - public ReturnToTheWindEffectCastFromExileEffect(final ReturnToTheWindEffectCastFromExileEffect effect) { + public ReleaseToTheWindEffectCastFromExileEffect(final ReleaseToTheWindEffectCastFromExileEffect effect) { super(effect); } @@ -125,8 +125,8 @@ class ReturnToTheWindEffectCastFromExileEffect extends AsThoughEffectImpl { } @Override - public ReturnToTheWindEffectCastFromExileEffect copy() { - return new ReturnToTheWindEffectCastFromExileEffect(this); + public ReleaseToTheWindEffectCastFromExileEffect copy() { + return new ReleaseToTheWindEffectCastFromExileEffect(this); } @Override diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index fc3640ab251..5e9cfaad8dd 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -28,7 +28,6 @@ package mage.sets; import mage.cards.ExpansionSet; -import mage.cards.o.OrazcaFrillback; import mage.constants.Rarity; import mage.constants.SetType; @@ -174,7 +173,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Negate", 44, Rarity.COMMON, mage.cards.n.Negate.class)); cards.add(new SetCardInfo("Nezahal, Primal Tide", 45, Rarity.RARE, mage.cards.n.NezahalPrimalTide.class)); cards.add(new SetCardInfo("Oathsworn Vampire", 80, Rarity.UNCOMMON, mage.cards.o.OathswornVampire.class)); - cards.add(new SetCardInfo("Orazca Frillback", 140, Rarity.COMMON, OrazcaFrillback.class)); + cards.add(new SetCardInfo("Orazca Frillback", 140, Rarity.COMMON, mage.cards.o.OrazcaFrillback.class)); cards.add(new SetCardInfo("Orazca Raptor", 108, Rarity.COMMON, mage.cards.o.OrazcaRaptor.class)); cards.add(new SetCardInfo("Orazca Relic", 181, Rarity.COMMON, mage.cards.o.OrazcaRelic.class)); cards.add(new SetCardInfo("Overgrown Armasaur", 141, Rarity.COMMON, mage.cards.o.OvergrownArmasaur.class)); @@ -199,7 +198,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Rekindling Phoenix", 111, Rarity.MYTHIC, mage.cards.r.RekindlingPhoenix.class)); cards.add(new SetCardInfo("Relentless Raptor", 169, Rarity.UNCOMMON, mage.cards.r.RelentlessRaptor.class)); cards.add(new SetCardInfo("Resplendent Griffin", 170, Rarity.UNCOMMON, mage.cards.r.ResplendentGriffin.class)); - cards.add(new SetCardInfo("Return to the Wind", 46, Rarity.RARE, mage.cards.r.ReturnToTheWind.class)); + cards.add(new SetCardInfo("Release to the Wind", 46, Rarity.RARE, mage.cards.r.ReleaseToTheWind.class)); cards.add(new SetCardInfo("River Darter", 47, Rarity.COMMON, mage.cards.r.RiverDarter.class)); cards.add(new SetCardInfo("Riverwise Augur", 48, Rarity.UNCOMMON, mage.cards.r.RiverwiseAugur.class)); cards.add(new SetCardInfo("Sadistic Skymarcher", 85, Rarity.UNCOMMON, mage.cards.s.SadisticSkymarcher.class)); From f7b562a976170354f5f560019a6778e280b22485 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 10:17:36 +0400 Subject: [PATCH 33/71] * Tilonalli's Crown - Fixed typo in the card name --- .../t/{TilonalisCrown.java => TilonallisCrown.java} | 12 ++++++------ Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename Mage.Sets/src/mage/cards/t/{TilonalisCrown.java => TilonallisCrown.java} (91%) diff --git a/Mage.Sets/src/mage/cards/t/TilonalisCrown.java b/Mage.Sets/src/mage/cards/t/TilonallisCrown.java similarity index 91% rename from Mage.Sets/src/mage/cards/t/TilonalisCrown.java rename to Mage.Sets/src/mage/cards/t/TilonallisCrown.java index 5ee365c9498..ccf5f0fd691 100644 --- a/Mage.Sets/src/mage/cards/t/TilonalisCrown.java +++ b/Mage.Sets/src/mage/cards/t/TilonallisCrown.java @@ -52,9 +52,9 @@ import mage.target.common.TargetCreaturePermanent; * * @author LevelX2 */ -public class TilonalisCrown extends CardImpl { +public class TilonallisCrown extends CardImpl { - public TilonalisCrown(UUID ownerId, CardSetInfo setInfo) { + public TilonallisCrown(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); this.subtype.add(SubType.AURA); @@ -66,7 +66,7 @@ public class TilonalisCrown extends CardImpl { Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - // When Tilonali's Crown enters the battlefield, it deals 1 damage to enchanted creature. + // When Tilonalli's Crown enters the battlefield, it deals 1 damage to enchanted creature. this.addAbility(new EntersBattlefieldTriggeredAbility(new DamageAttachedEffect(1, "it") .setText("it deals 1 damage to enchanted creature"))); @@ -78,12 +78,12 @@ public class TilonalisCrown extends CardImpl { this.addAbility(ability); } - public TilonalisCrown(final TilonalisCrown card) { + public TilonallisCrown(final TilonallisCrown card) { super(card); } @Override - public TilonalisCrown copy() { - return new TilonalisCrown(this); + public TilonallisCrown copy() { + return new TilonallisCrown(this); } } diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 5e9cfaad8dd..9e0eb91a344 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -245,7 +245,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("The Immortal Sun", 180, Rarity.MYTHIC, mage.cards.t.TheImmortalSun.class)); cards.add(new SetCardInfo("Thrashing Brontodon", 148, Rarity.UNCOMMON, mage.cards.t.ThrashingBrontodon.class)); cards.add(new SetCardInfo("Thunderherd Migration", 149, Rarity.UNCOMMON, mage.cards.t.ThunderherdMigration.class)); - cards.add(new SetCardInfo("Tilonali's Crown", 120, Rarity.COMMON, mage.cards.t.TilonalisCrown.class)); + cards.add(new SetCardInfo("Tilonalli's Crown", 120, Rarity.COMMON, mage.cards.t.TilonallisCrown.class)); cards.add(new SetCardInfo("Tilonalli's Summoner", 121, Rarity.RARE, mage.cards.t.TilonallisSummoner.class)); cards.add(new SetCardInfo("Timestream Navigator", 59, Rarity.MYTHIC, mage.cards.t.TimestreamNavigator.class)); cards.add(new SetCardInfo("Tomb of the Dusk Rose", "166b", Rarity.RARE, mage.cards.t.TombOfTheDuskRose.class)); From ea99c7fb723d1b878d9d9019e1cbf6cb0efec0f0 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 8 Jan 2018 10:24:26 +0400 Subject: [PATCH 34/71] * Voracious Vampire - Fixed missing ability text --- Mage.Sets/src/mage/cards/v/VoraciousVampire.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/v/VoraciousVampire.java b/Mage.Sets/src/mage/cards/v/VoraciousVampire.java index c45827d23ce..563661c7922 100644 --- a/Mage.Sets/src/mage/cards/v/VoraciousVampire.java +++ b/Mage.Sets/src/mage/cards/v/VoraciousVampire.java @@ -63,7 +63,7 @@ public class VoraciousVampire extends CardImpl { // When Voracious Vampire enters the battlefield, target Vampire you control gets +1/+1 and gains menace until end of turn. Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), false); Effect effect = new GainAbilityTargetEffect(new MenaceAbility(), Duration.EndOfTurn); - effect.setText("and gains menace"); + effect.setText("and gains menace until end of turn."); ability.addEffect(effect); ability.addTarget(new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent(SubType.VAMPIRE, "Vampire you control"))); this.addAbility(ability); From 096f2c0e51dde4558befc343b27d6eaa97f747f1 Mon Sep 17 00:00:00 2001 From: Mathieu Pouedras Date: Wed, 3 Jan 2018 12:12:19 +0100 Subject: [PATCH 35/71] Implements Brood of Cockroaches --- .../src/mage/cards/b/BroodOfCockroaches.java | 110 ++++++++++++++++++ Mage.Sets/src/mage/sets/Visions.java | 1 + .../single/vis/BroodOfCockroachesTest.java | 104 +++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java diff --git a/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java b/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java new file mode 100644 index 00000000000..0c9d652ca6c --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.Game; +import mage.target.targetpointer.FixedTarget; + +import static mage.constants.Outcome.Benefit; + +/** + * + * @author mpouedras + */ +public class BroodOfCockroaches extends CardImpl { + + public BroodOfCockroaches(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.INSECT); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Brood of Cockroaches is put into your graveyard from the battlefield, + // at the beginning of the next end step, + // you lose 1 life + // and return Brood of Cockroaches to your hand. + this.addAbility(new DiesTriggeredAbility(new BroodOfCockroachesEffect())); + } + + public BroodOfCockroaches(final BroodOfCockroaches card) { + super(card); + } + + @Override + public BroodOfCockroaches copy() { + return new BroodOfCockroaches(this); + } +} + +class BroodOfCockroachesEffect extends OneShotEffect { + private static final String effectText = "at the beginning of the next end step, you lose 1 life and return Brood of Cockroaches to your hand."; + + BroodOfCockroachesEffect() { + super(Benefit); + staticText = effectText; + } + + BroodOfCockroachesEffect(BroodOfCockroachesEffect broodOfCockroachesEffect) { + super(broodOfCockroachesEffect); + } + + @Override + public boolean apply(Game game, Ability source) { + AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedLifeLost = + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new LoseLifeSourceControllerEffect(1)); + game.addDelayedTriggeredAbility(delayedLifeLost, source); + + Effect effect = new ReturnToHandTargetEffect(); + effect.setText("return Brood of Cockroaches to your hand."); + effect.setTargetPointer(new FixedTarget(source.getSourceId(), source.getSourceObjectZoneChangeCounter())); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect); + game.addDelayedTriggeredAbility(delayedAbility, source); + + return true; + } + + @Override + public Effect copy() { + return new BroodOfCockroachesEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Visions.java b/Mage.Sets/src/mage/sets/Visions.java index 92817270e98..b537d3b33dd 100644 --- a/Mage.Sets/src/mage/sets/Visions.java +++ b/Mage.Sets/src/mage/sets/Visions.java @@ -63,6 +63,7 @@ public class Visions extends ExpansionSet { cards.add(new SetCardInfo("Brass-Talon Chimera", 142, Rarity.UNCOMMON, mage.cards.b.BrassTalonChimera.class)); cards.add(new SetCardInfo("Breathstealer's Crypt", 127, Rarity.RARE, mage.cards.b.BreathstealersCrypt.class)); cards.add(new SetCardInfo("Breezekeeper", 27, Rarity.COMMON, mage.cards.b.Breezekeeper.class)); + cards.add(new SetCardInfo("Brood of Cockroaches", 3, Rarity.UNCOMMON, mage.cards.b.BroodOfCockroaches.class)); cards.add(new SetCardInfo("Bull Elephant", 51, Rarity.COMMON, mage.cards.b.BullElephant.class)); cards.add(new SetCardInfo("Chronatog", 28, Rarity.RARE, mage.cards.c.Chronatog.class)); cards.add(new SetCardInfo("City of Solitude", 52, Rarity.RARE, mage.cards.c.CityOfSolitude.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java new file mode 100644 index 00000000000..d4133f297a8 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/vis/BroodOfCockroachesTest.java @@ -0,0 +1,104 @@ +package org.mage.test.cards.single.vis; + +import mage.game.permanent.Permanent; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +import static mage.constants.Zone.*; +import static mage.constants.PhaseStep.*; + +public class BroodOfCockroachesTest extends CardTestPlayerBase { + + private static final int TURN_1 = 1; + private static final int ANY_LIFE_TOTAL = 17; + private static final String BROOD_OF_COCKROACHES = "Brood of Cockroaches"; + private static final String SHOCK = "Shock"; + + @Test + public void should_display_correct_text() { + String expectedText = "When {this} dies, at the beginning of the next end step, you lose 1 life and return Brood of Cockroaches to your hand."; + + playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase(); + + setStopAt(TURN_1, END_TURN); + execute(); + + Permanent permanent = getPermanent(BROOD_OF_COCKROACHES, playerA); + assertThat(permanent.getAbilities().get(1).toString(), is(expectedText)); + + } + + @Test + public void should_reduce_life_of_playerA_by_1_at_the_beginning_of_the_next_end_step() { + playerA.setLife(ANY_LIFE_TOTAL, currentGame); + + playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase(); + + brood_of_cockroaches_diesat_precombat_main_phase(); + + setStopAt(TURN_1, END_TURN); + execute(); + + assertLife(playerA, ANY_LIFE_TOTAL - 1); + } + + @Test + public void should_not_reduce_life_of_playerA_by_1_at_post_combat_main_step() { + playerA.setLife(ANY_LIFE_TOTAL, currentGame); + + playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase(); + + brood_of_cockroaches_diesat_precombat_main_phase(); + + setStopAt(TURN_1, PRECOMBAT_MAIN); + execute(); + + assertLife(playerA, ANY_LIFE_TOTAL ); + } + + @Test + public void should_return_Brood_of_Cockroaches_to_playerA_hand_end_of_turn() { + playerA.setLife(ANY_LIFE_TOTAL, currentGame); + + playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase(); + + brood_of_cockroaches_diesat_precombat_main_phase(); + + setStopAt(TURN_1, END_TURN); + execute(); + + assertHandCount(playerA, BROOD_OF_COCKROACHES, 1); + } + + @Test + public void should_not_return_Brood_of_Cockroaches_to_playerA_at_post_combat_step() { + playerA.setLife(ANY_LIFE_TOTAL, currentGame); + + playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase(); + + brood_of_cockroaches_diesat_precombat_main_phase(); + + setStopAt(TURN_1, POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, BROOD_OF_COCKROACHES, 0); + } + + + private void brood_of_cockroaches_diesat_precombat_main_phase() { + addCard(BATTLEFIELD, playerB, "Mountain", 1); + addCard(HAND, playerB, SHOCK, 1); + castSpell(TURN_1, PRECOMBAT_MAIN, playerB, SHOCK, BROOD_OF_COCKROACHES); + } + + private void playerA_casts_Brood_of_Cockroaches_at_precombat_main_phase() { + addCard(BATTLEFIELD, playerA, "Swamp", 2); + addCard(HAND, playerA, BROOD_OF_COCKROACHES, 1); + castSpell(TURN_1, PRECOMBAT_MAIN, playerA, BROOD_OF_COCKROACHES); + } + + +} From f3a37553a528ac83e66821d07e8d3b52e272f799 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 8 Jan 2018 10:52:03 +0100 Subject: [PATCH 36/71] * Temple Altisaur - Fixed that the prevention effect was applied to all creatures, not just Dinosaurs (fixes #4364). --- Mage.Sets/src/mage/cards/t/TempleAltisaur.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/t/TempleAltisaur.java b/Mage.Sets/src/mage/cards/t/TempleAltisaur.java index 0a73840ec86..7cbdcaac3a1 100644 --- a/Mage.Sets/src/mage/cards/t/TempleAltisaur.java +++ b/Mage.Sets/src/mage/cards/t/TempleAltisaur.java @@ -102,6 +102,7 @@ class TempleAltisaurPreventEffect extends PreventionEffectImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && !permanent.getId().equals(source.getSourceId()) + && permanent.hasSubtype(SubType.DINOSAUR, game) && permanent.getControllerId().equals(source.getControllerId())) { return super.applies(event, source, game); } From 0fe65e99fa8a8c8a1ffe8fbca750c2d21475f1a3 Mon Sep 17 00:00:00 2001 From: Mathieu Pouedras Date: Mon, 8 Jan 2018 12:04:56 +0100 Subject: [PATCH 37/71] replace the name of the card with {this} for effect text --- Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java b/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java index 0c9d652ca6c..e1320b457b2 100644 --- a/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java +++ b/Mage.Sets/src/mage/cards/b/BroodOfCockroaches.java @@ -95,7 +95,7 @@ class BroodOfCockroachesEffect extends OneShotEffect { game.addDelayedTriggeredAbility(delayedLifeLost, source); Effect effect = new ReturnToHandTargetEffect(); - effect.setText("return Brood of Cockroaches to your hand."); + effect.setText("return {this} to your hand."); effect.setTargetPointer(new FixedTarget(source.getSourceId(), source.getSourceObjectZoneChangeCounter())); DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect); game.addDelayedTriggeredAbility(delayedAbility, source); From 9258621bf1919a97230b6e7b7fb82a498886d0a4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 8 Jan 2018 17:11:43 +0100 Subject: [PATCH 38/71] * Dead Man's - Fixed that cards were exiled from controllers lib instead of enchanted objects owner library (fixes #4374). --- Mage.Sets/src/mage/cards/d/DeadMansChest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/d/DeadMansChest.java b/Mage.Sets/src/mage/cards/d/DeadMansChest.java index b76c47f0011..a1a00a68cce 100644 --- a/Mage.Sets/src/mage/cards/d/DeadMansChest.java +++ b/Mage.Sets/src/mage/cards/d/DeadMansChest.java @@ -122,7 +122,7 @@ class DeadMansChestEffect extends OneShotEffect { Player owner = game.getPlayer(attachedTo.getOwnerId()); int amount = attachedTo.getPower().getValue(); if (owner != null && amount > 0) { - Set cards = controller.getLibrary().getTopCards(game, amount); + Set cards = owner.getLibrary().getTopCards(game, amount); if (!cards.isEmpty()) { controller.moveCardsToExile(cards, source, game, true, source.getSourceId(), sourceObject.getLogName()); for (Card card : cards) { From 6769630308f8079c0de45e2d7e425e3908a0912b Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Mon, 8 Jan 2018 17:00:08 +0000 Subject: [PATCH 39/71] Fixed ClassCastException for Baron Von Count --- Mage.Sets/src/mage/cards/b/BaronVonCount.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BaronVonCount.java b/Mage.Sets/src/mage/cards/b/BaronVonCount.java index 36cf00d6754..123e4819c16 100644 --- a/Mage.Sets/src/mage/cards/b/BaronVonCount.java +++ b/Mage.Sets/src/mage/cards/b/BaronVonCount.java @@ -196,8 +196,9 @@ class BaronVonCountMoveDoomCounterEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); MageObject mageObject = game.getObject(source.getSourceId()); - if (controller != null && mageObject != null) { + if (controller != null && sourcePermanent != null && mageObject != null) { if (game.getState().getValue(mageObject.getId() + "_doom") == null) { return false; } @@ -272,8 +273,9 @@ class BaronVonCountDestroyPlayerEffect extends OneShotEffect { game.informPlayers(targetPlayer.getLogName() + " was destroyed"); targetPlayer.lost(game); // double checks canLose, but seems more future-proof than lostForced } + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); MageObject mageObject = game.getObject(source.getSourceId()); - if (mageObject != null) { + if (sourcePermanent != null && mageObject != null) { if (game.getState().getValue(mageObject.getId() + "_doom") == null) { return false; } From 1109d2b246d548a5e4ad2f4625a9bd8490372af2 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Mon, 8 Jan 2018 17:23:12 +0000 Subject: [PATCH 40/71] Made Changeling take effect in all zones Still doesn't fix Path of Ancestry interaction of Dr. Julius Jumblemorph though --- .../src/main/java/mage/abilities/keyword/ChangelingAbility.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java b/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java index 009d3a2ea72..b01ce8447ac 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ChangelingAbility.java @@ -56,7 +56,7 @@ public class ChangelingAbility extends StaticAbility implements MageSingleton { } private ChangelingAbility() { - super(Zone.BATTLEFIELD, null); + super(Zone.ALL, null); } @Override From 121c0ff89418244a1cc2e629e82e42737976d3cf Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 8 Jan 2018 22:59:18 +0100 Subject: [PATCH 41/71] * Angrath, the Flame-Chained - Fixed that it's -3 ability did sac with conv. mana cost of >= 3 instead of <= 3. --- Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java b/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java index efb1758fb04..9d4decc3883 100644 --- a/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java +++ b/Mage.Sets/src/mage/cards/a/AngrathTheFlameChained.java @@ -143,7 +143,7 @@ class AngrathTheFlameCreateDelayedTriggerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null) { SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice this", source.getControllerId()); sacrificeEffect.setTargetPointer(new FixedTarget(permanent, game)); @@ -175,7 +175,7 @@ class AngrathTheFlameChainedDelayedTriggeredAbility extends DelayedTriggeredAbil Permanent permanent = game.getPermanent(((FixedTarget) getEffects().get(0).getTargetPointer()).getTarget()); return permanent != null && permanent.getZoneChangeCounter(game) == ((FixedTarget) getEffects().get(0).getTargetPointer()).getZoneChangeCounter() - && permanent.getConvertedManaCost() >= 3; + && permanent.getConvertedManaCost() <= 3; } @Override @@ -185,6 +185,6 @@ class AngrathTheFlameChainedDelayedTriggeredAbility extends DelayedTriggeredAbil @Override public String getRule() { - return "sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less."; + return "Sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less."; } } From fef0ef83ec9cb07dcd752b1c76e680a6ff8ed69d Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 8 Jan 2018 22:59:35 +0100 Subject: [PATCH 42/71] xmage 1.4.26V11c --- Mage.Common/src/main/java/mage/utils/MageVersion.java | 2 +- Mage.Sets/src/mage/cards/c/ChampionOfDusk.java | 11 +++++++---- .../java/mage/cards/repository/CardRepository.java | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index 26dd9ca6d3a..4a6adeb7dc4 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 26; - public final static String MAGE_VERSION_MINOR_PATCH = "V11b"; + public final static String MAGE_VERSION_MINOR_PATCH = "V11c"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java b/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java index 0fb0d72cc2d..b8721ab7624 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java +++ b/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; @@ -46,22 +47,24 @@ import mage.filter.predicate.mageobject.SubtypePredicate; * @author L_J */ public class ChampionOfDusk extends CardImpl { - private static FilterControlledPermanent filter = new FilterControlledPermanent("Vampires you control"); + + private final static FilterControlledPermanent filter = new FilterControlledPermanent("Vampires you control"); static { filter.add(new SubtypePredicate(SubType.VAMPIRE)); } public ChampionOfDusk(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.VAMPIRE); this.subtype.add(SubType.KNIGHT); this.power = new MageInt(4); this.toughness = new MageInt(4); // When Champion of Dusk enters the battlefield, you draw X cards and you lose X life, where X is the number of Vampires you control. - Ability ability = new EntersBattlefieldAbility(new DrawCardSourceControllerEffect(new PermanentsOnBattlefieldCount(filter))); - ability.addEffect(new LoseLifeSourceControllerEffect(new PermanentsOnBattlefieldCount(filter))); + DynamicValue xCount = new PermanentsOnBattlefieldCount(filter); + Ability ability = new EntersBattlefieldAbility(new DrawCardSourceControllerEffect(xCount)); + ability.addEffect(new LoseLifeSourceControllerEffect(xCount)); this.addAbility(ability); } diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index c2107071097..db9f2bf33f4 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -58,7 +58,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 51; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 98; + private static final long CARD_CONTENT_VERSION = 99; private Dao cardDao; private Set classNames; From b7b0310969481da92f3e9099ac81d9d24e117aa7 Mon Sep 17 00:00:00 2001 From: igoudt Date: Tue, 9 Jan 2018 00:07:06 +0100 Subject: [PATCH 43/71] fixes #4380 --- Mage.Sets/src/mage/cards/c/ChampionOfDusk.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java b/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java index b8721ab7624..372428c07ae 100644 --- a/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java +++ b/Mage.Sets/src/mage/cards/c/ChampionOfDusk.java @@ -27,10 +27,9 @@ */ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -42,6 +41,8 @@ import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; +import java.util.UUID; + /** * * @author L_J @@ -63,7 +64,7 @@ public class ChampionOfDusk extends CardImpl { // When Champion of Dusk enters the battlefield, you draw X cards and you lose X life, where X is the number of Vampires you control. DynamicValue xCount = new PermanentsOnBattlefieldCount(filter); - Ability ability = new EntersBattlefieldAbility(new DrawCardSourceControllerEffect(xCount)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(xCount)); ability.addEffect(new LoseLifeSourceControllerEffect(xCount)); this.addAbility(ability); } From 1a2e44ef20251952a891c9b9f34d61d53589bbf7 Mon Sep 17 00:00:00 2001 From: Achilles Date: Mon, 8 Jan 2018 20:18:25 -0600 Subject: [PATCH 44/71] - Fixed Rimefeather Owl. --- Mage.Sets/src/mage/cards/r/RimefeatherOwl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/r/RimefeatherOwl.java b/Mage.Sets/src/mage/cards/r/RimefeatherOwl.java index 0ffb468b39f..11f6bbd2d24 100644 --- a/Mage.Sets/src/mage/cards/r/RimefeatherOwl.java +++ b/Mage.Sets/src/mage/cards/r/RimefeatherOwl.java @@ -68,8 +68,8 @@ public class RimefeatherOwl extends CardImpl { private static final FilterPermanent filter2 = new FilterPermanent("snow permanents on the battlefield"); static { - filter.add(Predicates.not(new CounterPredicate(CounterType.ICE))); - filter2.add(Predicates.not(new SupertypePredicate(SuperType.SNOW))); + filter.add(new CounterPredicate(CounterType.ICE)); + filter2.add(new SupertypePredicate(SuperType.SNOW)); } public RimefeatherOwl(UUID ownerId, CardSetInfo setInfo) { From b353a25f572015bd5be5e3654277e118b9bff440 Mon Sep 17 00:00:00 2001 From: Achilles Date: Mon, 8 Jan 2018 21:19:15 -0600 Subject: [PATCH 45/71] - Fixed Remembrance. --- Mage.Sets/src/mage/cards/r/Remembrance.java | 32 ++++++++++++--------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Mage.Sets/src/mage/cards/r/Remembrance.java b/Mage.Sets/src/mage/cards/r/Remembrance.java index fc40e55d475..1b61cbf2b6e 100644 --- a/Mage.Sets/src/mage/cards/r/Remembrance.java +++ b/Mage.Sets/src/mage/cards/r/Remembrance.java @@ -28,6 +28,7 @@ package mage.cards.r; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; @@ -57,13 +58,6 @@ import mage.target.common.TargetCardInLibrary; */ public class Remembrance extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature you control"); - - static { - filter.add(new ControllerPredicate(TargetController.YOU)); - filter.add(Predicates.not(new TokenPredicate())); - } - public Remembrance(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); @@ -83,8 +77,15 @@ public class Remembrance extends CardImpl { class RemembranceTriggeredAbility extends TriggeredAbilityImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.not(new TokenPredicate())); + } + public RemembranceTriggeredAbility() { - super(Zone.BATTLEFIELD, null); + super(Zone.BATTLEFIELD, new RemembranceEffect()); this.optional = true; } @@ -107,9 +108,10 @@ class RemembranceTriggeredAbility extends TriggeredAbilityImpl { if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent != null && permanent.getControllerId().equals(this.getControllerId()) && permanent.isCreature()) { - this.getEffects().clear(); - this.addEffect(new RemembranceEffect(permanent.getName())); + MageObject mageObject = game.getObject(sourceId); + if (permanent != null + && filter.match(permanent, game)) { + game.getState().setValue(mageObject + "nameOfPermanent", permanent.getName()); return true; } } @@ -126,9 +128,8 @@ class RemembranceEffect extends OneShotEffect { private String cardName; - RemembranceEffect(String cardName) { + RemembranceEffect() { super(Outcome.Benefit); - this.cardName = cardName; } RemembranceEffect(final RemembranceEffect effect) { @@ -143,7 +144,10 @@ class RemembranceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + MageObject mageObject = game.getObject(source.getSourceId()); + cardName = (String) game.getState().getValue(mageObject + "nameOfPermanent"); + if (controller != null + && cardName != null) { FilterCard filterCard = new FilterCard("card named " + cardName); filterCard.add(new NamePredicate(cardName)); return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true, true).apply(game, source); From 8e3b610a0c0cc1284d9b10b712d21856e36dc30a Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 9 Jan 2018 19:27:25 +0400 Subject: [PATCH 46/71] Tests: fixed performance problem (x20 speed up, no need to call full garbage collector manually) --- Mage.Client/src/main/java/mage/client/cards/CardGrid.java | 1 - .../java/org/mage/plugins/card/images/DownloadPictures.java | 2 +- .../mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/cards/CardGrid.java b/Mage.Client/src/main/java/mage/client/cards/CardGrid.java index fe918f797d2..8f2f2fa9e01 100644 --- a/Mage.Client/src/main/java/mage/client/cards/CardGrid.java +++ b/Mage.Client/src/main/java/mage/client/cards/CardGrid.java @@ -122,7 +122,6 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener, addCard(card, bigCard, gameId, drawImage); } } - // System.gc(); drawCards(sortSetting); this.setVisible(true); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 08e350a2137..26ce8adc734 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -648,7 +648,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab logger.fatal("Couldn't unmount zip files", e); JOptionPane.showMessageDialog(null, "Couldn't unmount zip files", "Error", JOptionPane.ERROR_MESSAGE); } finally { - System.gc(); + // } closeButton.setText("Close"); updateCardsToDownload(jComboBoxSet.getSelectedItem().toString()); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 537d8b18422..ba66640d759 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -116,7 +116,6 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement if (currentGame != null) { logger.debug("Resetting previous game and creating new one!"); currentGame = null; - System.gc(); } currentGame = createNewGameAndPlayers(); From 79c18d28e2ba09af42568070ec8aa68bbfd246c6 Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 12:40:39 -0800 Subject: [PATCH 47/71] Implement Chicken Egg --- Mage.Sets/src/mage/cards/c/ChickenEgg.java | 77 +++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + .../src/main/java/mage/constants/SubType.java | 2 + .../permanent/token/GiantChickenToken.java | 18 +++++ 4 files changed, 98 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/ChickenEgg.java create mode 100644 Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java diff --git a/Mage.Sets/src/mage/cards/c/ChickenEgg.java b/Mage.Sets/src/mage/cards/c/ChickenEgg.java new file mode 100644 index 00000000000..e25ee82fc7e --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChickenEgg.java @@ -0,0 +1,77 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.game.permanent.token.GiantChickenToken; +import mage.players.Player; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ + +public class ChickenEgg extends CardImpl { + + public ChickenEgg(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.EGG); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // At the beginning of your upkeep, roll a six-sided die. If you roll a 6, sacrifice Chicken Egg and create a 4/4 red Giant Chicken creature token. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ChickenEggEffect(), TargetController.YOU, false)); + } + + public ChickenEgg(final ChickenEgg card) { + super(card); + } + + @Override + public ChickenEgg copy() { + return new ChickenEgg(this); + } +} + +class ChickenEggEffect extends OneShotEffect { + + ChickenEggEffect() { + super(Outcome.Benefit); + this.staticText = "roll a six-sided die. If you roll a 6, sacrifice {this} and create a 4/4 red Giant Chicken creature token"; + } + + ChickenEggEffect(final ChickenEggEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int result = controller.rollDice(game, 6); + if (result == 6) { + new SacrificeSourceEffect().apply(game, source); + return (new CreateTokenEffect(new GiantChickenToken(), 1)).apply(game, source); + } + } + return false; + } + + @Override + public ChickenEggEffect copy() { + return new ChickenEggEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 824c1b65b80..7c83ce1e062 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -20,6 +20,7 @@ public class Unglued extends ExpansionSet { private Unglued() { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); + cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 276dcfd1897..ddbb44d31f0 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -85,6 +85,7 @@ public enum SubType { CENTAUR("Centaur", SubTypeSet.CreatureType), CEREAN("Cerean", SubTypeSet.CreatureType, true), // Star Wars CEPHALID("Cephalid", SubTypeSet.CreatureType), + CHICKEN("Chicken", SubTypeSet.CreatureType), CHIMERA("Chimera", SubTypeSet.CreatureType), CHISS("Chiss", SubTypeSet.CreatureType, true), CITIZEN("Citizen", SubTypeSet.CreatureType), @@ -114,6 +115,7 @@ public enum SubType { DWARF("Dwarf", SubTypeSet.CreatureType), // E EFREET("Efreet", SubTypeSet.CreatureType), + EGG("Egg", SubTypeSet.CreatureType), ELDER("Elder", SubTypeSet.CreatureType), ELDRAZI("Eldrazi", SubTypeSet.CreatureType), ELEMENTAL("Elemental", SubTypeSet.CreatureType), diff --git a/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java b/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java new file mode 100644 index 00000000000..71d93e91af2 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java @@ -0,0 +1,18 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +public class GiantChickenToken extends Token { + + public GiantChickenToken() { + super("Giant Chicken", "4/4 red Giant Chicken creature token"); + cardType.add(CardType.CREATURE); + color.setRed(true); + subtype.add(SubType.GIANT); + subtype.add(SubType.CHICKEN); + power = new MageInt(4); + toughness = new MageInt(4); + } +} From 3e87a50b4d5197023f24a0169b242dae6f493639 Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 13:25:46 -0800 Subject: [PATCH 48/71] Implement Krazy Kow --- Mage.Sets/src/mage/cards/c/ChickenEgg.java | 27 +++++ Mage.Sets/src/mage/cards/k/KrazyKow.java | 102 ++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + .../src/main/java/mage/constants/SubType.java | 3 +- .../permanent/token/GiantChickenToken.java | 32 ++++++ 5 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/k/KrazyKow.java diff --git a/Mage.Sets/src/mage/cards/c/ChickenEgg.java b/Mage.Sets/src/mage/cards/c/ChickenEgg.java index e25ee82fc7e..8f09a83c9ab 100644 --- a/Mage.Sets/src/mage/cards/c/ChickenEgg.java +++ b/Mage.Sets/src/mage/cards/c/ChickenEgg.java @@ -1,3 +1,30 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.cards.c; import mage.MageInt; diff --git a/Mage.Sets/src/mage/cards/k/KrazyKow.java b/Mage.Sets/src/mage/cards/k/KrazyKow.java new file mode 100644 index 00000000000..3fa78b45e27 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KrazyKow.java @@ -0,0 +1,102 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ + +public class KrazyKow extends CardImpl { + + public KrazyKow(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.COW); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // At the beginning of your upkeep, roll a six-sided die. If you a roll a 1, sacrifice Krazy Kow and it deals 3 damage to each creature and each player. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new KrazyKowEffect(), TargetController.YOU, false)); + } + + public KrazyKow(final KrazyKow card) { + super(card); + } + + @Override + public KrazyKow copy() { + return new KrazyKow(this); + } +} + +class KrazyKowEffect extends OneShotEffect { + KrazyKowEffect() { + super(Outcome.Benefit); + this.staticText = "roll a six-sided die. If you roll a 1, sacrifice {this} and it deals 3 damage to each creature and each player"; + } + + KrazyKowEffect(final KrazyKowEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int result = controller.rollDice(game, 6); + if (result == 1) { + new SacrificeSourceEffect().apply(game, source); + return new DamageEverythingEffect(3).apply(game, source); + } + } + return false; + } + + @Override + public KrazyKowEffect copy() { + return new KrazyKowEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 7c83ce1e062..55d5cd17645 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -21,6 +21,7 @@ public class Unglued extends ExpansionSet { private Unglued() { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); + cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index ddbb44d31f0..51a4b58ae2c 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -85,13 +85,14 @@ public enum SubType { CENTAUR("Centaur", SubTypeSet.CreatureType), CEREAN("Cerean", SubTypeSet.CreatureType, true), // Star Wars CEPHALID("Cephalid", SubTypeSet.CreatureType), - CHICKEN("Chicken", SubTypeSet.CreatureType), + CHICKEN("Chicken", SubTypeSet.CreatureType), // Unglued CHIMERA("Chimera", SubTypeSet.CreatureType), CHISS("Chiss", SubTypeSet.CreatureType, true), CITIZEN("Citizen", SubTypeSet.CreatureType), CLERIC("Cleric", SubTypeSet.CreatureType), COCKATRICE("Cockatrice", SubTypeSet.CreatureType), CONSTRUCT("Construct", SubTypeSet.CreatureType), + COW("Cow", SubTypeSet.CreatureType), // Unglued COWARD("Coward", SubTypeSet.CreatureType), CRAB("Crab", SubTypeSet.CreatureType), CROCODILE("Crocodile", SubTypeSet.CreatureType), diff --git a/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java b/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java index 71d93e91af2..8b814efdc05 100644 --- a/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/GiantChickenToken.java @@ -1,9 +1,41 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.game.permanent.token; import mage.MageInt; import mage.constants.CardType; import mage.constants.SubType; +/** + * + * @author ciaccona007 + */ + public class GiantChickenToken extends Token { public GiantChickenToken() { From 5db12db371ba56d2199a559472f651a9ca10342c Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 13:58:23 -0800 Subject: [PATCH 49/71] Implement Growth Spurt --- Mage.Sets/src/mage/cards/g/GrowthSpurt.java | 99 +++++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + 2 files changed, 100 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GrowthSpurt.java diff --git a/Mage.Sets/src/mage/cards/g/GrowthSpurt.java b/Mage.Sets/src/mage/cards/g/GrowthSpurt.java new file mode 100644 index 00000000000..1e27dd000e6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GrowthSpurt.java @@ -0,0 +1,99 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.cards.g; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +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.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ +public class GrowthSpurt extends CardImpl { + + public GrowthSpurt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new GrowthSpurtEffect()); + } + + public GrowthSpurt(final GrowthSpurt card) { + super(card); + } + + @Override + public GrowthSpurt copy() { + return new GrowthSpurt(this); + } +} + +class GrowthSpurtEffect extends OneShotEffect { + GrowthSpurtEffect() { + super(Outcome.BoostCreature); + this.staticText = "todo"; //TODO + } + + GrowthSpurtEffect(final GrowthSpurtEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int result = controller.rollDice(game, 6); + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + ContinuousEffect effect = new BoostTargetEffect(result, result, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + } + } + return false; + } + + public GrowthSpurtEffect copy() { + return new GrowthSpurtEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 55d5cd17645..47058990f12 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -22,6 +22,7 @@ public class Unglued extends ExpansionSet { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); + cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); From d9b14acec717000a37b60d4d93074658c952fdbd Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 14:59:13 -0700 Subject: [PATCH 50/71] Implement Growth Spurt (#4386) --- Mage.Sets/src/mage/cards/g/GrowthSpurt.java | 99 +++++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + 2 files changed, 100 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GrowthSpurt.java diff --git a/Mage.Sets/src/mage/cards/g/GrowthSpurt.java b/Mage.Sets/src/mage/cards/g/GrowthSpurt.java new file mode 100644 index 00000000000..1e27dd000e6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GrowthSpurt.java @@ -0,0 +1,99 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.cards.g; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +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.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ +public class GrowthSpurt extends CardImpl { + + public GrowthSpurt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new GrowthSpurtEffect()); + } + + public GrowthSpurt(final GrowthSpurt card) { + super(card); + } + + @Override + public GrowthSpurt copy() { + return new GrowthSpurt(this); + } +} + +class GrowthSpurtEffect extends OneShotEffect { + GrowthSpurtEffect() { + super(Outcome.BoostCreature); + this.staticText = "todo"; //TODO + } + + GrowthSpurtEffect(final GrowthSpurtEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int result = controller.rollDice(game, 6); + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + ContinuousEffect effect = new BoostTargetEffect(result, result, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + } + } + return false; + } + + public GrowthSpurtEffect copy() { + return new GrowthSpurtEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 55d5cd17645..47058990f12 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -22,6 +22,7 @@ public class Unglued extends ExpansionSet { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); + cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); From 470bb69a7e9a2e751773c30ac5bcd34f7cc02f5c Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 14:14:34 -0800 Subject: [PATCH 51/71] Implement Timmy, Power Gamer --- .../src/mage/cards/t/TimmyPowerGamer.java | 76 +++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + .../src/main/java/mage/constants/SubType.java | 1 + 3 files changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TimmyPowerGamer.java diff --git a/Mage.Sets/src/mage/cards/t/TimmyPowerGamer.java b/Mage.Sets/src/mage/cards/t/TimmyPowerGamer.java new file mode 100644 index 00000000000..84b635f6b2c --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TimmyPowerGamer.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.PutPermanentOnBattlefieldEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ +public class TimmyPowerGamer extends CardImpl { + + public TimmyPowerGamer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.GAMER); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {4}: You may put a creature card from your hand onto the battlefield. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new PutPermanentOnBattlefieldEffect(new FilterCreatureCard("a creature card")), + new ManaCostsImpl("{4}")); + this.addAbility(ability); + } + + public TimmyPowerGamer(final TimmyPowerGamer card) { + super(card); + } + + @Override + public TimmyPowerGamer copy() { + return new TimmyPowerGamer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 47058990f12..f2d3d12902e 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -23,6 +23,7 @@ public class Unglued extends ExpansionSet { cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); + cards.add(new SetCardInfo("Timmy, Power Gamer", 68, Rarity.RARE, mage.cards.t.TimmyPowerGamer.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 51a4b58ae2c..a893adab284 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -134,6 +134,7 @@ public enum SubType { FROG("Frog", SubTypeSet.CreatureType), FUNGUS("Fungus", SubTypeSet.CreatureType), // G + GAMER("Gamer", SubTypeSet.CreatureType), // Un-sets GAMORREAN("Gamorrean", SubTypeSet.CreatureType, true), // Star Wars GAND("Gand", SubTypeSet.CreatureType, true), // Star Wars GARGOYLE("Gargoyle", SubTypeSet.CreatureType), From 77d90c5997ecc1c22c82a5f3b083364c270ecf36 Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 16:25:20 -0800 Subject: [PATCH 52/71] Implement Poultrygeist --- Mage.Sets/src/mage/cards/p/Poultrygeist.java | 111 +++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + 2 files changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/Poultrygeist.java diff --git a/Mage.Sets/src/mage/cards/p/Poultrygeist.java b/Mage.Sets/src/mage/cards/p/Poultrygeist.java new file mode 100644 index 00000000000..838d2415458 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/Poultrygeist.java @@ -0,0 +1,111 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ +public class Poultrygeist extends CardImpl { + + public Poultrygeist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}"); + this.subtype.add(SubType.CHICKEN); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever a creature dies, you may roll a six-sided die. If you roll a 1, sacrifice Poultrygeist. Otherwise, put a +1/+1 counter on Poultrygeist. + Ability ability = new DiesCreatureTriggeredAbility(new PoultrygeistEffect(), true); + this.addAbility(ability); + } + + public Poultrygeist(final Poultrygeist card) { + super(card); + } + + @Override + public Poultrygeist copy() { + return new Poultrygeist(this); + } +} + +class PoultrygeistEffect extends OneShotEffect { + + PoultrygeistEffect() { + super(Outcome.BoostCreature); + this.staticText = "roll a six-sided die. If you roll a 1, sacrifice {this}. Otherwise, put a +1/+1 counter on {this}"; + } + + PoultrygeistEffect(final PoultrygeistEffect ability) { + super(ability); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int result = controller.rollDice(game, 6); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if (result == 1) { + return permanent.sacrifice(source.getSourceId(), game); + } else { + return new AddCountersSourceEffect(CounterType.P1P1.createInstance()).apply(game, source); + } + } + } + return false; + } + + @Override + public PoultrygeistEffect copy() { + return new PoultrygeistEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index f2d3d12902e..cc63178106f 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -20,6 +20,7 @@ public class Unglued extends ExpansionSet { private Unglued() { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); + cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class)); cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); From 408b0af7f1420d3ee3d96ccf460637058271a38b Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 16:31:16 -0800 Subject: [PATCH 53/71] Implement Poultrygeist --- Mage.Sets/src/mage/cards/p/Poultrygeist.java | 111 +++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + 2 files changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/Poultrygeist.java diff --git a/Mage.Sets/src/mage/cards/p/Poultrygeist.java b/Mage.Sets/src/mage/cards/p/Poultrygeist.java new file mode 100644 index 00000000000..838d2415458 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/Poultrygeist.java @@ -0,0 +1,111 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * + * @author ciaccona007 + */ +public class Poultrygeist extends CardImpl { + + public Poultrygeist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}"); + this.subtype.add(SubType.CHICKEN); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever a creature dies, you may roll a six-sided die. If you roll a 1, sacrifice Poultrygeist. Otherwise, put a +1/+1 counter on Poultrygeist. + Ability ability = new DiesCreatureTriggeredAbility(new PoultrygeistEffect(), true); + this.addAbility(ability); + } + + public Poultrygeist(final Poultrygeist card) { + super(card); + } + + @Override + public Poultrygeist copy() { + return new Poultrygeist(this); + } +} + +class PoultrygeistEffect extends OneShotEffect { + + PoultrygeistEffect() { + super(Outcome.BoostCreature); + this.staticText = "roll a six-sided die. If you roll a 1, sacrifice {this}. Otherwise, put a +1/+1 counter on {this}"; + } + + PoultrygeistEffect(final PoultrygeistEffect ability) { + super(ability); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int result = controller.rollDice(game, 6); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if (result == 1) { + return permanent.sacrifice(source.getSourceId(), game); + } else { + return new AddCountersSourceEffect(CounterType.P1P1.createInstance()).apply(game, source); + } + } + } + return false; + } + + @Override + public PoultrygeistEffect copy() { + return new PoultrygeistEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index f2d3d12902e..cc63178106f 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -20,6 +20,7 @@ public class Unglued extends ExpansionSet { private Unglued() { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); + cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class)); cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); From c7c8ee390d6f26b174077a09ccaa7459604675e0 Mon Sep 17 00:00:00 2001 From: ciaccona007 Date: Tue, 9 Jan 2018 19:13:00 -0800 Subject: [PATCH 54/71] Fix RIX land rarity --- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 9e0eb91a344..3589deae5bb 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -120,7 +120,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Forerunner of the Empire", 102, Rarity.UNCOMMON, mage.cards.f.ForerunnerOfTheEmpire.class)); cards.add(new SetCardInfo("Forerunner of the Heralds", 129, Rarity.UNCOMMON, mage.cards.f.ForerunnerOfTheHeralds.class)); cards.add(new SetCardInfo("Forerunner of the Legion", 9, Rarity.UNCOMMON, mage.cards.f.ForerunnerOfTheLegion.class)); - cards.add(new SetCardInfo("Forest", 196, Rarity.COMMON, mage.cards.basiclands.Forest.class)); + cards.add(new SetCardInfo("Forest", 196, Rarity.LAND, mage.cards.basiclands.Forest.class)); cards.add(new SetCardInfo("Form of the Dinosaur", 103, Rarity.RARE, mage.cards.f.FormOfTheDinosaur.class)); cards.add(new SetCardInfo("Forsaken Sanctuary", 187, Rarity.UNCOMMON, mage.cards.f.ForsakenSanctuary.class)); cards.add(new SetCardInfo("Foul Orchard", 188, Rarity.UNCOMMON, mage.cards.f.FoulOrchard.class)); @@ -143,7 +143,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Impale", 76, Rarity.COMMON, mage.cards.i.Impale.class)); cards.add(new SetCardInfo("Imperial Ceratops", 10, Rarity.UNCOMMON, mage.cards.i.ImperialCeratops.class)); cards.add(new SetCardInfo("Induced Amnesia", 40, Rarity.RARE, mage.cards.i.InducedAmnesia.class)); - cards.add(new SetCardInfo("Island", 193, Rarity.COMMON, mage.cards.basiclands.Island.class)); + cards.add(new SetCardInfo("Island", 193, Rarity.LAND, mage.cards.basiclands.Island.class)); cards.add(new SetCardInfo("Jade Bearer", 134, Rarity.COMMON, mage.cards.j.JadeBearer.class)); cards.add(new SetCardInfo("Jadecraft Artisan", 135, Rarity.COMMON, mage.cards.j.JadecraftArtisan.class)); cards.add(new SetCardInfo("Jadelight Ranger", 136, Rarity.RARE, mage.cards.j.JadelightRanger.class)); @@ -166,7 +166,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Mist-Cloaked Herald", 43, Rarity.COMMON, mage.cards.m.MistCloakedHerald.class)); cards.add(new SetCardInfo("Moment of Craving", 79, Rarity.COMMON, mage.cards.m.MomentOfCraving.class)); cards.add(new SetCardInfo("Moment of Triumph", 15, Rarity.COMMON, mage.cards.m.MomentOfTriumph.class)); - cards.add(new SetCardInfo("Mountain", 195, Rarity.COMMON, mage.cards.basiclands.Mountain.class)); + cards.add(new SetCardInfo("Mountain", 195, Rarity.LAND, mage.cards.basiclands.Mountain.class)); cards.add(new SetCardInfo("Mutiny", 106, Rarity.COMMON, mage.cards.m.Mutiny.class)); cards.add(new SetCardInfo("Naturalize", 139, Rarity.COMMON, mage.cards.n.Naturalize.class)); cards.add(new SetCardInfo("Needletooth Raptor", 107, Rarity.UNCOMMON, mage.cards.n.NeedletoothRaptor.class)); @@ -182,7 +182,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Path of Mettle", "165a", Rarity.RARE, mage.cards.p.PathOfMettle.class)); cards.add(new SetCardInfo("Pirate's Pillage", 109, Rarity.UNCOMMON, mage.cards.p.PiratesPillage.class)); cards.add(new SetCardInfo("Pitiless Plunderer", 81, Rarity.UNCOMMON, mage.cards.p.PitilessPlunderer.class)); - cards.add(new SetCardInfo("Plains", 192, Rarity.COMMON, mage.cards.basiclands.Plains.class)); + cards.add(new SetCardInfo("Plains", 192, Rarity.LAND, mage.cards.basiclands.Plains.class)); cards.add(new SetCardInfo("Plummet", 143, Rarity.COMMON, mage.cards.p.Plummet.class)); cards.add(new SetCardInfo("Polyraptor", 144, Rarity.MYTHIC, mage.cards.p.Polyraptor.class)); cards.add(new SetCardInfo("Pride of Conquerors", 17, Rarity.UNCOMMON, mage.cards.p.PrideOfConquerors.class)); @@ -236,7 +236,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Sun-Crested Pterodon", 27, Rarity.COMMON, mage.cards.s.SunCrestedPterodon.class)); cards.add(new SetCardInfo("Swab Goblin", 203, Rarity.COMMON, mage.cards.s.SwabGoblin.class)); cards.add(new SetCardInfo("Swaggering Corsair", 119, Rarity.COMMON, mage.cards.s.SwaggeringCorsair.class)); - cards.add(new SetCardInfo("Swamp", 194, Rarity.COMMON, mage.cards.basiclands.Swamp.class)); + cards.add(new SetCardInfo("Swamp", 194, Rarity.LAND, mage.cards.basiclands.Swamp.class)); cards.add(new SetCardInfo("Swift Warden", 146, Rarity.UNCOMMON, mage.cards.s.SwiftWarden.class)); cards.add(new SetCardInfo("Sworn Guardian", 58, Rarity.COMMON, mage.cards.s.SwornGuardian.class)); cards.add(new SetCardInfo("Temple Altisaur", 28, Rarity.RARE, mage.cards.t.TempleAltisaur.class)); From 9598ffa16b3df39cdb3b4ffc0da4883abc5cb1e1 Mon Sep 17 00:00:00 2001 From: spjspj Date: Wed, 10 Jan 2018 20:02:37 +1100 Subject: [PATCH 55/71] Add Jack-in-the-Mox + Jumbo Imp (UGL) --- Mage.Sets/src/mage/cards/j/JackInTheMox.java | 119 +++++++++++++ Mage.Sets/src/mage/cards/j/JumboImp.java | 177 +++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 11 +- 3 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/j/JackInTheMox.java create mode 100644 Mage.Sets/src/mage/cards/j/JumboImp.java diff --git a/Mage.Sets/src/mage/cards/j/JackInTheMox.java b/Mage.Sets/src/mage/cards/j/JackInTheMox.java new file mode 100644 index 00000000000..b1bef7d4257 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JackInTheMox.java @@ -0,0 +1,119 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.j; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author spjspj + */ +public class JackInTheMox extends CardImpl { + + public JackInTheMox(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}"); + + // {T}: Roll a six-sided die. This ability has the indicated effect. + // 1 - Sacrifice Jack-in-the-Mox and you lose 5 life. + // 2 - Add {W} to your mana pool. + // 3 - Add {U} to your mana pool. + // 4 - Add {B} to your mana pool. + // 5 - Add {R} to your mana pool. + // 6 - Add {G} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new JackInTheMoxManaEffect(), new TapSourceCost()); + this.addAbility(ability); + } + + public JackInTheMox(final JackInTheMox card) { + super(card); + } + + @Override + public JackInTheMox copy() { + return new JackInTheMox(this); + } +} + +class JackInTheMoxManaEffect extends ManaEffect { + + JackInTheMoxManaEffect() { + super(); + staticText = "Roll a six-sided die. If result is 1 - Sacrifice {this} and you lose 5 life. 2 - Add {W} 3 - Add {U} 4 - Add {B} 5 - Add {R} 6 - Add {G} to your mana pool"; + } + + JackInTheMoxManaEffect(final JackInTheMoxManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + int amount = controller.rollDice(game, 6); + if (amount == 1) { + permanent.sacrifice(source.getSourceId(), game); + controller.loseLife(5, game, false); + } else if (amount == 2) { + controller.getManaPool().addMana(Mana.WhiteMana(1), game, source); + } else if (amount == 3) { + controller.getManaPool().addMana(Mana.BlueMana(1), game, source); + } else if (amount == 4) { + controller.getManaPool().addMana(Mana.BlackMana(1), game, source); + } else if (amount == 5) { + controller.getManaPool().addMana(Mana.RedMana(1), game, source); + } else if (amount == 6) { + controller.getManaPool().addMana(Mana.GreenMana(1), game, source); + } + return true; + } + return false; + } + + @Override + public JackInTheMoxManaEffect copy() { + return new JackInTheMoxManaEffect(this); + } + + @Override + public Mana getMana(Game game, Ability source) { + return null; + } +} diff --git a/Mage.Sets/src/mage/cards/j/JumboImp.java b/Mage.Sets/src/mage/cards/j/JumboImp.java new file mode 100644 index 00000000000..bd7f5ef02f3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JumboImp.java @@ -0,0 +1,177 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.j; + +import java.util.ArrayList; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.Counter; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author spjspj + */ +public class JumboImp extends CardImpl { + + public JumboImp(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.IMP); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // As Jumbo Imp enters the battlefield, roll a six-sided die. Jumbo Imp enters the battlefield with a number of +1/+1 counters on it equal to the result. + this.addAbility(new EntersBattlefieldAbility(new JumboImpEffect(new Counter("P1P1")))); + + // At the beginning of your upkeep, roll a six-sided die and put a number of +1/+1 counters on Jumbo Imp equal to the result. + Ability ability2 = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new JumboImpAddCountersEffect(), TargetController.YOU, false); + this.addAbility(ability2); + + // At the beginning of your end step, roll a six-sided die and remove a number of +1/+1 counters from Jumbo Imp equal to the result. + Ability ability3 = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new JumboImpRemoveCountersEffect(), TargetController.YOU, null, false); + this.addAbility(ability3); + } + + public JumboImp(final JumboImp card) { + super(card); + } + + @Override + public JumboImp copy() { + return new JumboImp(this); + } +} + +class JumboImpEffect extends EntersBattlefieldWithXCountersEffect { + + public JumboImpEffect(Counter counter) { + super(counter); + } + + public JumboImpEffect(EntersBattlefieldWithXCountersEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanentEntering(source.getSourceId()); + if (controller != null && permanent != null) { + int amount = controller.rollDice(game, 6); + ArrayList appliedEffects = (ArrayList) this.getValue("appldiedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event + permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game, appliedEffects); + return super.apply(game, source); + } + return false; + } + + @Override + public EntersBattlefieldWithXCountersEffect copy() { + return new JumboImpEffect(this); + } + +} + +class JumboImpAddCountersEffect extends OneShotEffect { + + public JumboImpAddCountersEffect() { + super(Outcome.Benefit); + this.staticText = "roll a six-sided die and put a number of +1/+1 counters on {this} equal to the result"; + } + + public JumboImpAddCountersEffect(final JumboImpAddCountersEffect effect) { + super(effect); + } + + @Override + public JumboImpAddCountersEffect copy() { + return new JumboImpAddCountersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + int amount = controller.rollDice(game, 6); + permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); + return true; + } + return false; + } +} + +class JumboImpRemoveCountersEffect extends OneShotEffect { + + public JumboImpRemoveCountersEffect() { + super(Outcome.Detriment); + this.staticText = "roll a six-sided die and remove a number of +1/+1 counters on {this} equal to the result"; + } + + public JumboImpRemoveCountersEffect(final JumboImpRemoveCountersEffect effect) { + super(effect); + } + + @Override + public JumboImpRemoveCountersEffect copy() { + return new JumboImpRemoveCountersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + int amount = controller.rollDice(game, 6); + permanent.removeCounters(CounterType.P1P1.createInstance(amount), game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index cc63178106f..ec858d5289e 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -20,15 +20,18 @@ public class Unglued extends ExpansionSet { private Unglued() { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); - cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class)); + cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); - cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); - cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); - cards.add(new SetCardInfo("Timmy, Power Gamer", 68, Rarity.RARE, mage.cards.t.TimmyPowerGamer.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("Jack-in-the-Mox", 75, Rarity.RARE, mage.cards.j.JackInTheMox.class)); + cards.add(new SetCardInfo("Jumbo Imp", 34, Rarity.UNCOMMON, mage.cards.j.JumboImp.class)); + cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Plains", 84, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class)); cards.add(new SetCardInfo("Swamp", 86, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("Timmy, Power Gamer", 68, Rarity.RARE, mage.cards.t.TimmyPowerGamer.class)); } } From da69ee88164b59566a455c5b61612b9f51ada602 Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 11 Jan 2018 00:12:05 +1100 Subject: [PATCH 56/71] Add Chicken a la King (UGL) --- .../src/mage/cards/c/ChickenALaKing.java | 135 ++++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 1 + Utils/mtg-cards-data.txt | 46 +++++- 3 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/c/ChickenALaKing.java diff --git a/Mage.Sets/src/mage/cards/c/ChickenALaKing.java b/Mage.Sets/src/mage/cards/c/ChickenALaKing.java new file mode 100644 index 00000000000..e12636431ff --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChickenALaKing.java @@ -0,0 +1,135 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.common.RollDiceEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author spjspj + */ +public class ChickenALaKing extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Chicken you control"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + filter.add(new SubtypePredicate(SubType.CHICKEN)); + } + + public ChickenALaKing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); + + this.subtype.add(SubType.CHICKEN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever a 6 is rolled on a six-sided die, put a +1/+1 counter on each Chicken. + this.addAbility(new ChickenALaKingTriggeredAbility()); + + // Tap an untapped Chicken you control: Roll a six-sided die. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RollDiceEffect(null, Outcome.Benefit, 6), new TapTargetCost(new TargetControlledPermanent(1, 1, filter, false)))); + } + + public ChickenALaKing(final ChickenALaKing card) { + super(card); + } + + @Override + public ChickenALaKing copy() { + return new ChickenALaKing(this); + } +} + +class ChickenALaKingTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each Chicken"); + + static { + filter.add(new SubtypePredicate(SubType.CHICKEN)); + } + + public ChickenALaKingTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter)); + } + + public ChickenALaKingTriggeredAbility(final ChickenALaKingTriggeredAbility ability) { + super(ability); + } + + @Override + public ChickenALaKingTriggeredAbility copy() { + return new ChickenALaKingTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DICE_ROLLED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (this.getControllerId().equals(event.getPlayerId()) && event.getFlag()) { + // event.getData holds the num of sides of the die to roll + String data = event.getData(); + if (data != null) { + int numSides = Integer.parseInt(data); + if (event.getAmount() == 6 && numSides == 6) { + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a 6 is rolled on a six-sided die, put a +1/+1 counter on each Chicken"; + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index ec858d5289e..9e33d2e77c3 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -22,6 +22,7 @@ public class Unglued extends ExpansionSet { super("Unglued", "UGL", ExpansionSet.buildDate(1998, 8, 11), SetType.JOKESET); cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); + cards.add(new SetCardInfo("Chicken a la King", 17, Rarity.RARE, mage.cards.c.ChickenALaKing.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index f9e2c86284b..1eb98fc23ca 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32970,7 +32970,7 @@ Willing Test Subject|Unstable|126|C|{2}{G}|Creature- Spider Monkey Scientist|2|2 Garbage Elemental|Unstable|82|U|{4}{R}|Creature - Elemental|3|2|Battle cry (Whenever this creature attacks, each other attacking creature gets +1/+0 until end of turn.)$When Garbage Elemental enters the battlefield, roll two six-sided dice. Create a number of 1/1 red Goblin creature tokens equal to the difference between those results.| Oddly Uneven|Unstable|15|R|{3}{W}{W}|Sorcery|||Choose one --$* Destroy each creature with an odd number of words in its name. (Hyphenated words are one word.)$* Destroy each creature with an even number of words in its name.| capital offense|Unstable|52|C|{2}{B}{B}|Instant|||target creature gets -x/-x until end of turn, where x is the number of times a capital letter appears in its rules text. (ignore reminder text and flavor text.) -Very Cryptic Command|Unstable|49|R|{1}{U}{U}{U}|Instant|||Choose two - Return target permanent to its controller�s hand.; Draw two cards, then discard a card.; Change the target of target spell with a single target.; Turn over target nontoken creature.| +Very Cryptic Command|Unstable|49|R|{1}{U}{U}{U}|Instant|||Choose two - Return target permanent to its controller's hand.; Draw two cards, then discard a card.; Change the target of target spell with a single target.; Turn over target nontoken creature.| Master of Waves|Duel Decks: Merfolk vs. Goblins|1|M|{3}{U}|Creature - Merfolk Wizard|2|1|Protection from red$Elemental creatures you control get +1/+1.$When Master of Waves enters the battlefield, create a number of 1/0 blue Elemental creature tokens equal to your devotion to blue. (Each {U} in the mana costs of permanents you control counts toward your devotion to blue.)| Aquitect's Will|Duel Decks: Merfolk vs. Goblins|2|C|{U}|Tribal Sorcery - Merfolk|||Put a flood counter on target land. That land is an Island in addition to its other types for as long as it has a flood counter on it. If you control a Merfolk, draw a card.| Claustrophobia|Duel Decks: Merfolk vs. Goblins|3|C|{1}{U}{U}|Enchantment - Aura|||Enchant creature$When Claustrophobia enters the battlefield, tap enchanted creature.$Enchanted creature doesn't untap during its controller's untap step.| @@ -33030,3 +33030,47 @@ Blighted Gorge|Duel Decks: Merfolk vs. Goblins|58|U||Land|||{tap}: Add {C} to yo Forgotten Cave|Duel Decks: Merfolk vs. Goblins|59|C||Land|||Forgotten Cave enters the battlefield tapped.${tap}: Add {R} to your mana pool.$Cycling {R} ({R}, Discard this card: Draw a card.)| Mountain|Duel Decks: Merfolk vs. Goblins|60|L||Basic Land - Mountain|||| Mountain|Duel Decks: Merfolk vs. Goblins|61|L||Basic Land - Mountain|||| +The Cheese Stands Alone|Unglued|2|R|{4}{W}{W}|Enchantment|||When you control no permanents other than The Cheese Stands Alone and have no cards in hand, you win the game.| +Lexivore|Unglued|7|U|{3}{W}|Creature - Beast|2|3| Whenever Lexivore deals damage to a player, destroy target permanent other than Lexivore with the most lines of text in its text box. (If two or more cards are tied, target any one of them.)| +Miss Demeanor|Unglued|10|U|{3}{W}|Creature - Lady of Proper Etiquette|3|1| Flying, first strike At the beginning of each other player's upkeep, you may compliment that player on his or her game play. If you don't, sacrifice Miss Demeanor.| +Once More with Feeling|Unglued|11|R|{W}{W}{W}{W}|Sorcery|||Exile all permanents and all cards from all graveyards. Each player shuffles his or her hand into his or her library, then draws seven cards. Each player's life total becomes 10. Exile Once More with Feeling. DCI ruling - A deck can have only one card named Once More with Feeling.| +Checks and Balances|Unglued|16|U|{2}{U}|Enchantment|||Cast Checks and Balances only if there are three or more players in the game. Whenever a player casts a spell, each of that player's opponents may discard a card. If they do, counter that spell.| +Chicken a la King|Unglued|17|R|{1}{U}{U}|Creature - Chicken|2|2| Whenever a 6 is rolled on a six-sided die, put a +1/+1 counter on each Chicken. (You may roll dice only when instructed to.) Tap an untapped Chicken you control: Roll a six-sided die.| +Clambassadors|Unglued|18|C|{3}{U}|Creature - Clamfolk|4|4| Whenever Clambassadors deals damage to a player, choose an artifact, creature, or land you control. That player gains control of that permanent.| +Clam-I-Am|Unglued|19|C|{2}{U}|Creature - Clamfolk|2|2| If you roll a 3 on a six-sided die, you may reroll that die.| +Denied!|Unglued|22|C|{U}|Instant|||Choose a card name, then target spell's controller reveals his or her hand. If a card with the chosen name is revealed this way, counter that spell.| +Fowl Play|Unglued|24|C|{2}{U}|Enchantment - Aura|||Enchant creature Enchanted creature is a Chicken with base power and toughness 1/1 and loses all abilities.| +Free-for-All|Unglued|25|R|{3}{U}|Enchantment|||When Free-for-All enters the battlefield, exile all creatures face down. At the beginning of each player's upkeep, that player chooses a card exiled with Free-for-All at random and puts it onto the battlefield. When Free-for-All leaves the battlefield, put all cards exiled with it into their owners' graveyards.| +Psychic Network|Unglued|26|R|{U}|Enchantment|||Each player plays with the top card of his or her library held against his or her forehead, revealed to each other player.| +Deadhead|Unglued|30|C|{3}{B}|Creature - Zombie|3|3| {0}: Return Deadhead from your graveyard to the battlefield. Activate this ability only if an opponent isn't touching his or her hand (of cards).| +Jumbo Imp|Unglued|34|U|{2}{B}|Creature - Imp|0|0| Flying$As Jumbo Imp enters the battlefield, roll a six-sided die. Jumbo Imp enters the battlefield with a number of +1/+1 counters on it equal to the result.$At the beginning of your upkeep, roll a six-sided die and put a number of +1/+1 counters on Jumbo Imp equal to the result. At the beginning of your end step, roll a six-sided die and remove a number of +1/+1 counters from Jumbo Imp equal to the result.| +Organ Harvest|Unglued|35|C|{B}|Sorcery|||Your team may sacrifice any number of creatures. For each creature sacrificed this way, you add {B}{B} to your mana pool.| +Poultrygeist|Unglued|37|C|{2}{B}|Creature - Chicken|1|1| Flying Whenever a creature dies, you may roll a six-sided die. If you roll a 1, sacrifice Poultrygeist. Otherwise, put a +1/+1 counter on Poultrygeist.| +Temp of the Damned|Unglued|38|C|{2}{B}|Creature - Zombie|3|3| As Temp of the Damned enters the battlefield, roll a six-sided die. Temp of the Damned enters the battlefield with a number of funk counters on it equal to the result. At the beginning of your upkeep, remove a funk counter from Temp of the Damned. If you can't, sacrifice it.| +Burning Cinder Fury of Crimson Chaos Fire|Unglued|40|R|{3}{R}|Enchantment|||Whenever any player taps a permanent, that player choose one of his or her opponents. The chosen player gains control of that permanent at the beginning of the next end step. At the beginning of each player's end step, if that player didn't tap any nonland permanents that turn, Burning Cinder Fury of Crimson Chaos Fire deals 3 damage to that player.| +Chicken Egg|Unglued|41|R|{1}{R}|Creature - Egg|0|1| At the beginning of your upkeep, roll a six-sided die. If you roll a 6, sacrifice Chicken Egg and create a 4/4 red Giant Chicken creature token.| +Goblin Bookie|Unglued|43|C|{R}|Creature - Goblin|1|1| {R}, {T}: Reflip any coin or reroll any die. (Activate this ability only any time it makes sense.)| +Goblin Bowling Team|Unglued|44|C|{3}{R}|Creature - Goblin|1|1| If Goblin Bowling Team would deal damage to a creature or player, it deals that much damage plus the result of a six-sided die roll to that creature or player instead.| +Goblin Tutor|Unglued|45|U|{R}|Instant|||Roll a six-sided die. If you roll a 1, Goblin Tutor has no effect. Otherwise, search your library for the indicated card, reveal it, put it into your hand, then shuffle your library. 2 - A card named Goblin Tutor 3 - An enchantment card 4 - An artifact card 5 - A creature card 6 - An instant or sorcery card| +Jalum Grifter|Unglued|47|R|{3}{R}{R}|Legendary Creature - Devil|3|5| {1}{R}, {T}: Shuffle Jalum Grifter and two lands you control face down. Target opponent chooses one of those cards. Turn the cards face up. If the opponent chose Jalum Grifter, sacrifice it. Otherwise, destroy target permanent.| +Krazy Kow|Unglued|48|C|{3}{R}|Creature - Cow|3|3| At the beginning of your upkeep, roll a six-sided die. If you a roll a 1, sacrifice Krazy Kow and it deals 3 damage to each creature and each player.| +Ricochet|Unglued|50|U|{R}|Enchantment|||Whenever a player casts a spell that targets a single player, each player rolls a six-sided die. Change the target of that spell to the player with the lowest result. Reroll to break ties, if necessary.| +Spark Fiend|Unglued|51|R|{4}{R}|Creature - Beast, When Spark Fiend enters the battlefield, roll two six-sided dice. If you rolled 2, 3, or 12, sacrifice Spark Fiend. If you rolled 7 or 11, don't roll dice for Spark Fiend during any of your following upkeeps. If you rolled any other total, note that total. At the beginning of your upkeep, roll two six-sided dice. If you rolled 7, sacrifice Spark Fiend. If you roll the noted total, don't roll dice for Spark Fiend during any of your following upkeeps. Otherwise, do nothing.| +Strategy, Schmategy|Unglued|52|R|{1}{R}|Sorcery|||Roll a six-sided die. Strategy, Schmategy has the indicated effect. 1 - Do nothing. 2 - Destroy all artifacts. 3 - Destroy all lands. 4 - Strategy, Schmategy deals 3 damage to each creature and each player. 5 - Each player discards his or her hand and draws seven cards. 6 - Repeat this process two more times.| +The Ultimate Nightmare of Wizards of the Coast Customer Service|Unglued|53|U|{X}{Y}{Z}{R}{R}|Sorcery|||The Ultimate Nightmare of Wizards of the Coast® Customer Service deals X damage to each of Y target creatures and Z target players.| +Elvish Impersonators|Unglued|56|C|{3}{G}|Creature - Elves, */*, As Elvish Impersonators enters the battlefield, roll a six-sided die twice. Its base power becomes the first result and its base toughness becomes the second result.| +Flock of Rabid Sheep|Unglued|57|U|{X}{G}{G}|Sorcery|||Flip X coins. For each flip you win, create a 2/2 green Sheep creature token named Rabid Sheep.| +Free-Range Chicken|Unglued|58|C|{3}{G}|Creature - Chicken|3|3| {1}{G}: Roll two six-sided dice. If both results are the same, Free-Range Chicken gets +X/+X until end of turn, where X is that result. If the total of those results is equal to any other total you have rolled this turn for Free-Range Chicken, sacrifice it. (For example, if you roll two 3s, Free-Range Chicken gets +3/+3. If you roll a total of 6 for Free-Range Chicken later that turn, sacrifice it.)| +Gerrymandering|Unglued|59|U|{2}{G}|Sorcery|||Exile all lands. Give each player a number of those cards chosen at random equal to the number of those cards the player controlled. Each player returns those cards to the battlefield under that player's control.| +Growth Spurt|Unglued|61|C|{1}{G}|Instant|||Roll a six-sided die. Target creature gets +X/+X until end of turn, where X is the result.| +Hungry Hungry Heifer|Unglued|63|U|{2}{G}|Creature - Cow|3|3| At the beginning of your upkeep, you may remove a counter from a permanent you control. If you don't, sacrifice Hungry Hungry Heifer.| +Incoming!|Unglued|64|R|{4}{G}{G}{G}{G}|Sorcery|||Each player searches his or her library for any number of artifact, creature, enchantment, and/or land cards, puts them onto the battlefield, then shuffles his or her library.| +Team Spirit|Unglued|67|C|{2}{G}|Instant|||Creatures target player's team controls get +1/+1 until end of turn.| +Timmy, Power Gamer|Unglued|68|R|{2}{G}{G}|Legendary Creature - Human Gamer|1|1| {4}: You may put a creature card from your hand onto the battlefield.| +Giant Fan|Unglued|74|R|{4}|Artifact|||{2}, {T}: Move a counter from one permanent onto another. If the second permanent refers to any kind of counter, the moved counter becomes one of those counters. Otherwise, it becomes a +1/+1 counter.| +Jack-in-the-Mox|Unglued|75|R|{0}|Artifact|||{T}: Roll a six-sided die. This ability has the indicated effect. 1 - Sacrifice Jack-in-the-Mox and you lose 5 life. 2 - Add {W} to your mana pool. 3 - Add {U} to your mana pool. 4 - Add {B} to your mana pool. 5 - Add {R} to your mana pool. 6 - Add {G} to your mana pool.| +Paper Tiger|Unglued|78|C|{4}|Artifact Creature - Cat|4|3| Creatures named Rock Lobster can't attack or block.| +Rock Lobster|Unglued|79|C|{4}|Artifact Creature - Lobster|4|3| Creatures named Scissors Lizard can't attack or block.| +Scissors Lizard|Unglued|80|C|{4}|Artifact Creature - Lizard|4|3| Creatures named Paper Tiger can't attack or block.| +Spatula of the Ages|Unglued|81|U|{4}|Artifact|||{4}, {T}, Sacrifice Spatula of the Ages: You may put a silver-bordered permanent card from your hand onto the battlefield.| +Urza's Science Fair Project|Unglued|83|U|{6}|Artifact Creature - Construct|4|4| {2}: Roll a six-sided die. Urza's Science Fair Project gets the indicated result. 1 - It gets -2/-2 until end of turn. 2 - Prevent all combat damage it would deal this turn. 3 - It gains vigilance until end of turn. 4 - It gains first strike until end of turn. 5 - It gains flying until end of turn. 6 - It gets +2/+2 until end of turn.| From 79bdd2ca8fc3a70f98b3fddb023ab30d8ba53a70 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Wed, 10 Jan 2018 20:53:25 +0400 Subject: [PATCH 57/71] Tests: fixed server load test for simple connection and game starting --- Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java index ce2f5670eeb..240064072b4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java @@ -8,6 +8,7 @@ import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.ColoredManaSymbol; +import mage.constants.MatchTimeLimit; import mage.constants.MultiplayerAttackOption; import mage.constants.RangeOfInfluence; import mage.game.match.MatchOptions; @@ -275,6 +276,7 @@ public class LoadTest { options.setAttackOption(MultiplayerAttackOption.MULTIPLE); options.setRange(RangeOfInfluence.ALL); options.setWinsNeeded(1); + options.setMatchTimeLimit(MatchTimeLimit.MIN__15); return options; } From 4f38939fc1f9acb15b749c14aa2d73fc39e65f60 Mon Sep 17 00:00:00 2001 From: Administrator Date: Wed, 10 Jan 2018 11:56:51 -0600 Subject: [PATCH 58/71] - Fixed Pride of Conquerors. --- Mage.Sets/src/mage/cards/p/PrideOfConquerors.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java b/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java index d3c701e329b..21e9f0bc531 100644 --- a/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java +++ b/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java @@ -31,7 +31,6 @@ import java.util.UUID; import mage.abilities.condition.common.CitysBlessingCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.keyword.AscendEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -52,7 +51,7 @@ public class PrideOfConquerors extends CardImpl { // Creatures you control get +1/+1 until end of turn. If you have the city's blessing, those creatures get +2/+2 until end of turn instead. this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostControlledEffect(2, 2, Duration.EndOfTurn), - new BoostTargetEffect(1, 1, Duration.EndOfTurn), CitysBlessingCondition.instance, + new BoostControlledEffect(1, 1, Duration.EndOfTurn), CitysBlessingCondition.instance, "Creatures you control get +1/+1 until end of turn. If you have the city's blessing, those creatures get +2/+2 until end of turn instead")); } From 56c615a66f14b11fa2a357c90749e2f252e25f61 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 10 Jan 2018 18:09:09 +0000 Subject: [PATCH 59/71] Prohibit fix --- Mage.Sets/src/mage/cards/p/Prohibit.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/Prohibit.java b/Mage.Sets/src/mage/cards/p/Prohibit.java index 1fe93900788..3ae6ee0bebf 100644 --- a/Mage.Sets/src/mage/cards/p/Prohibit.java +++ b/Mage.Sets/src/mage/cards/p/Prohibit.java @@ -31,7 +31,6 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.KickedCondition; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -55,7 +54,7 @@ public class Prohibit extends CardImpl { this.addAbility(new KickerAbility("{2}")); // Counter target spell if its converted mana cost is 2 or less. If Prohibit was kicked, counter that spell if its converted mana cost is 4 or less instead. - this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addEffect(new ProhibitEffect()); this.getSpellAbility().addTarget(new TargetSpell()); } @@ -69,20 +68,20 @@ public class Prohibit extends CardImpl { } } -class OverloadEffect extends OneShotEffect { +class ProhibitEffect extends OneShotEffect { - OverloadEffect() { + ProhibitEffect() { super(Outcome.DestroyPermanent); this.staticText = "Counter target spell if its converted mana cost is 2 or less. If {this} was kicked, counter that spell if its converted mana cost is 4 or less instead."; } - OverloadEffect(final OverloadEffect effect) { + ProhibitEffect(final ProhibitEffect effect) { super(effect); } @Override - public OverloadEffect copy() { - return new OverloadEffect(this); + public ProhibitEffect copy() { + return new ProhibitEffect(this); } @Override From 8f9356533d45bf32ff45f58a07905183fa3b8a61 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 10 Jan 2018 19:44:48 +0000 Subject: [PATCH 60/71] Fixed undoing individual blocker declarations for multi-blockers One more #4172 fix --- .../main/java/mage/game/combat/Combat.java | 199 +++++++++++++++++- 1 file changed, 193 insertions(+), 6 deletions(-) diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index 159f950b76e..ea592fb47bb 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -678,6 +678,82 @@ public class Combat implements Serializable, Copyable { potentialBlockers.add(creature.getId()); } } + // check the mustBlockAllAttackers requirement (Blaze of Glory) ------------------------------- + if (effect.mustBlockAllAttackers(game)) { + Set attackersToBlock = new HashSet<>(); + // check that it can block at least one of the attackers + // and no restictions prevent this + boolean mayBlock = false; + for (UUID attackingCreatureId : getAttackers()) { + if (creature.canBlock(attackingCreatureId, game)) { + Permanent attackingCreature = game.getPermanent(attackingCreatureId); + if (attackingCreature != null) { + // check if the attacker is already blocked by a max of blockers, so blocker can't block it also + if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers + int alreadyBlockingCreatures = 0; + for (CombatGroup group : getGroups()) { + if (group.getAttackers().contains(attackingCreatureId)) { + alreadyBlockingCreatures = group.getBlockers().size(); + break; + } + } + if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) { + // Attacker can't be blocked by more blockers so check next attacker + continue; + } + } + // check restrictions of the creature to block that prevent it can be blocked + + if (attackingCreature.getMinBlockedBy() > 1) { + // TODO: check if enough possible blockers are available, if true, mayBlock can be set to true + + } else { + attackersToBlock.add(attackingCreatureId); + } + } + } + } + //~ // remove creatures already blocked by affected creature + //~ for (CombatGroup group : getBlockingGroups()) { + //~ if (group.getAttackers().contains(attackingCreatureId)) { + //~ for (UUID attackingCreatureId : group.getAttackers()) { + //~ CombatGroup attackersGroup = findGroup(attackingCreatureId); + //~ if (attackersGroup != null) { + //~ if (attackersGroup.getBlockers().contains(creature.getId())) { + //~ attackersToBlock.remove(attackingCreatureId); + //~ } + //~ } + //~ } + //~ } + //~ } + if (!attackersToBlock.isEmpty()) { + if (attackersToBlock.size() > creature.getBlocking()) { + mayBlock = true; + } + } + // if so inform human player or set block for AI player + if (mayBlock) { + if (controller.isHuman()) { + if (!game.isSimulation()) { + game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName()); + } + } else { + Player defender = game.getPlayer(creature.getControllerId()); + if (defender != null) { + for (UUID attackingCreatureId : getAttackers()) { + if (creature.canBlock(attackingCreatureId, game)) { + // ??? + if (attackersToBlock.contains(attackingCreatureId)) { + //~ defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); + addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game); + } + } + } + } + } + return false; + } + } } } @@ -701,8 +777,8 @@ public class Combat implements Serializable, Copyable { } } - // check the mustBlockAny requirement ---------------------------------------- - if (effect.mustBlockAny(game)) { + // check the mustBlockAny requirement ---------------------------------------- (and mustBlockAllAttackers for AI) + if (effect.mustBlockAny(game) || effect.mustBlockAllAttackers(game)) { // check that it can block at least one of the attackers // and no restictions prevent this boolean mayBlock = false; @@ -740,15 +816,28 @@ public class Combat implements Serializable, Copyable { if (mayBlock) { if (controller.isHuman()) { if (!game.isSimulation()) { - game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName()); + if (!effect.mustBlockAllAttackers(game)) { + game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName()); + } else { + game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName()); + } } } else { Player defender = game.getPlayer(creature.getControllerId()); if (defender != null) { for (UUID attackingCreatureId : getAttackers()) { if (creature.canBlock(attackingCreatureId, game)) { - defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); - break; + if (!effect.mustBlockAllAttackers(game)) { + defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); + break; + } else { + // this might be buggy with additional restriction effects + if (creature.getBlocking() == 0) { + defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); + } else { + addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game); + } + } } } } @@ -756,6 +845,82 @@ public class Combat implements Serializable, Copyable { return false; } } + /* + // check the mustBlockAllAttackers requirement ------------------------------- + if (effect.mustBlockAllAttackers(game)) { + Set attackersToBlock = new HashSet<>(); + // check that it can block at least one of the attackers + // and no restictions prevent this + boolean mayBlock = false; + for (UUID attackingCreatureId : getAttackers()) { + if (creature.canBlock(attackingCreatureId, game)) { + Permanent attackingCreature = game.getPermanent(attackingCreatureId); + if (attackingCreature != null) { + // check if the attacker is already blocked by a max of blockers, so blocker can't block it also + if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers + int alreadyBlockingCreatures = 0; + for (CombatGroup group : getGroups()) { + if (group.getAttackers().contains(attackingCreatureId)) { + alreadyBlockingCreatures = group.getBlockers().size(); + break; + } + } + if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) { + // Attacker can't be blocked by more blockers so check next attacker + continue; + } + } + // check restrictions of the creature to block that prevent it can be blocked + + if (attackingCreature.getMinBlockedBy() > 1) { + // TODO: check if enough possible blockers are available, if true, mayBlock can be set to true + + } else { + attackersToBlock.add(attackingCreatureId); + } + } + } + } + if (!attackersToBlock.isEmpty()) { + //~ CombatGroup group = findGroupOfBlocker(creature.getId()); + //~ if (group == null) { + //~ mayBlock = true; + //~ } else { + //~ for (UUID attackingCreatureId : attackersToBlock) { + //~ if (!group.getAttackers().contains(attackingCreatureId)) { + //~ mayBlock = true; + //~ break; + //~ } + //~ } + game.informPlayers(attackersToBlock.size() + " and " + creature.getBlocking()); + if (attackersToBlock.size() > creature.getBlocking()) { + mayBlock = true; + } + //~ } + } + // if so inform human player or set block for AI player + if (mayBlock) { + if (controller.isHuman()) { + if (!game.isSimulation()) { + game.informPlayer(controller, "Creature should block all attackers if able this turn: " + creature.getIdName()); + } + } else { + Player defender = game.getPlayer(creature.getControllerId()); + if (defender != null) { + for (UUID attackingCreatureId : getAttackers()) { + if (creature.canBlock(attackingCreatureId, game)) { + // ??? + if (attackersToBlock.contains(attackingCreatureId)) { + defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); + } + } + } + } + } + return false; + } + } + */ } } @@ -1180,6 +1345,7 @@ public class Combat implements Serializable, Copyable { //TODO: handle banding blockingGroups.get(blockerId).attackers.add(attackerId); } + // "blocker.setBlocking(blocker.getBlocking() + 1)" is handled by the attacking combat group } } @@ -1392,6 +1558,7 @@ public class Combat implements Serializable, Copyable { } public void removeBlockerGromGroup(UUID blockerId, CombatGroup groupToUnblock, Game game) { + // Manual player action for undoing one declared blocker (used for multi-blocker creatures) Permanent creature = game.getPermanent(blockerId); if (creature != null) { for (CombatGroup group : groups) { @@ -1404,7 +1571,26 @@ public class Combat implements Serializable, Copyable { if (creature.getBlocking() > 0) { creature.setBlocking(creature.getBlocking() - 1); } else { - throw new UnsupportedOperationException("Tryinging creature to unblock, but blocking number value of creature < 1"); + throw new UnsupportedOperationException("Trying to unblock creature, but blocking number value of creature < 1"); + } + boolean canRemove = false; + for (CombatGroup blockGroup : getBlockingGroups()) { + if (blockGroup.blockers.contains(blockerId)) { + for (UUID attackerId : group.getAttackers()) { + blockGroup.attackers.remove(attackerId); + blockGroup.attackerOrder.remove(attackerId); + } + if (creature.getBlocking() == 0) { + blockGroup.blockers.remove(blockerId); + blockGroup.attackerOrder.clear(); + } + } + if (blockGroup.blockers.isEmpty()) { + canRemove = true; + } + } + if (canRemove) { + blockingGroups.remove(blockerId); } } } @@ -1412,6 +1598,7 @@ public class Combat implements Serializable, Copyable { } public void removeBlocker(UUID blockerId, Game game) { + // Manual player action for undoing all declared blockers (used for single-blocker creatures and multi-blockers exceeding blocking limit) for (CombatGroup group : groups) { if (group.blockers.contains(blockerId)) { group.blockers.remove(blockerId); From a38ec84581e9399ddbbcd308f6b4c16ae31d75a2 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 10 Jan 2018 19:49:15 +0000 Subject: [PATCH 61/71] Removed slipped beta Blaze of Glory code in case it could break something, as it's still buggy --- .../main/java/mage/game/combat/Combat.java | 175 +----------------- 1 file changed, 5 insertions(+), 170 deletions(-) diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index ea592fb47bb..f6a76d8aefc 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -678,82 +678,6 @@ public class Combat implements Serializable, Copyable { potentialBlockers.add(creature.getId()); } } - // check the mustBlockAllAttackers requirement (Blaze of Glory) ------------------------------- - if (effect.mustBlockAllAttackers(game)) { - Set attackersToBlock = new HashSet<>(); - // check that it can block at least one of the attackers - // and no restictions prevent this - boolean mayBlock = false; - for (UUID attackingCreatureId : getAttackers()) { - if (creature.canBlock(attackingCreatureId, game)) { - Permanent attackingCreature = game.getPermanent(attackingCreatureId); - if (attackingCreature != null) { - // check if the attacker is already blocked by a max of blockers, so blocker can't block it also - if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers - int alreadyBlockingCreatures = 0; - for (CombatGroup group : getGroups()) { - if (group.getAttackers().contains(attackingCreatureId)) { - alreadyBlockingCreatures = group.getBlockers().size(); - break; - } - } - if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) { - // Attacker can't be blocked by more blockers so check next attacker - continue; - } - } - // check restrictions of the creature to block that prevent it can be blocked - - if (attackingCreature.getMinBlockedBy() > 1) { - // TODO: check if enough possible blockers are available, if true, mayBlock can be set to true - - } else { - attackersToBlock.add(attackingCreatureId); - } - } - } - } - //~ // remove creatures already blocked by affected creature - //~ for (CombatGroup group : getBlockingGroups()) { - //~ if (group.getAttackers().contains(attackingCreatureId)) { - //~ for (UUID attackingCreatureId : group.getAttackers()) { - //~ CombatGroup attackersGroup = findGroup(attackingCreatureId); - //~ if (attackersGroup != null) { - //~ if (attackersGroup.getBlockers().contains(creature.getId())) { - //~ attackersToBlock.remove(attackingCreatureId); - //~ } - //~ } - //~ } - //~ } - //~ } - if (!attackersToBlock.isEmpty()) { - if (attackersToBlock.size() > creature.getBlocking()) { - mayBlock = true; - } - } - // if so inform human player or set block for AI player - if (mayBlock) { - if (controller.isHuman()) { - if (!game.isSimulation()) { - game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName()); - } - } else { - Player defender = game.getPlayer(creature.getControllerId()); - if (defender != null) { - for (UUID attackingCreatureId : getAttackers()) { - if (creature.canBlock(attackingCreatureId, game)) { - // ??? - if (attackersToBlock.contains(attackingCreatureId)) { - //~ defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); - addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game); - } - } - } - } - } - return false; - } - } } } @@ -777,8 +701,8 @@ public class Combat implements Serializable, Copyable { } } - // check the mustBlockAny requirement ---------------------------------------- (and mustBlockAllAttackers for AI) - if (effect.mustBlockAny(game) || effect.mustBlockAllAttackers(game)) { + // check the mustBlockAny requirement ---------------------------------------- + if (effect.mustBlockAny(game)) { // check that it can block at least one of the attackers // and no restictions prevent this boolean mayBlock = false; @@ -816,28 +740,15 @@ public class Combat implements Serializable, Copyable { if (mayBlock) { if (controller.isHuman()) { if (!game.isSimulation()) { - if (!effect.mustBlockAllAttackers(game)) { - game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName()); - } else { - game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName()); - } + game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName()); } } else { Player defender = game.getPlayer(creature.getControllerId()); if (defender != null) { for (UUID attackingCreatureId : getAttackers()) { if (creature.canBlock(attackingCreatureId, game)) { - if (!effect.mustBlockAllAttackers(game)) { - defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); - break; - } else { - // this might be buggy with additional restriction effects - if (creature.getBlocking() == 0) { - defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); - } else { - addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game); - } - } + defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); + break; } } } @@ -845,82 +756,6 @@ public class Combat implements Serializable, Copyable { return false; } } - /* - // check the mustBlockAllAttackers requirement ------------------------------- - if (effect.mustBlockAllAttackers(game)) { - Set attackersToBlock = new HashSet<>(); - // check that it can block at least one of the attackers - // and no restictions prevent this - boolean mayBlock = false; - for (UUID attackingCreatureId : getAttackers()) { - if (creature.canBlock(attackingCreatureId, game)) { - Permanent attackingCreature = game.getPermanent(attackingCreatureId); - if (attackingCreature != null) { - // check if the attacker is already blocked by a max of blockers, so blocker can't block it also - if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers - int alreadyBlockingCreatures = 0; - for (CombatGroup group : getGroups()) { - if (group.getAttackers().contains(attackingCreatureId)) { - alreadyBlockingCreatures = group.getBlockers().size(); - break; - } - } - if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) { - // Attacker can't be blocked by more blockers so check next attacker - continue; - } - } - // check restrictions of the creature to block that prevent it can be blocked - - if (attackingCreature.getMinBlockedBy() > 1) { - // TODO: check if enough possible blockers are available, if true, mayBlock can be set to true - - } else { - attackersToBlock.add(attackingCreatureId); - } - } - } - } - if (!attackersToBlock.isEmpty()) { - //~ CombatGroup group = findGroupOfBlocker(creature.getId()); - //~ if (group == null) { - //~ mayBlock = true; - //~ } else { - //~ for (UUID attackingCreatureId : attackersToBlock) { - //~ if (!group.getAttackers().contains(attackingCreatureId)) { - //~ mayBlock = true; - //~ break; - //~ } - //~ } - game.informPlayers(attackersToBlock.size() + " and " + creature.getBlocking()); - if (attackersToBlock.size() > creature.getBlocking()) { - mayBlock = true; - } - //~ } - } - // if so inform human player or set block for AI player - if (mayBlock) { - if (controller.isHuman()) { - if (!game.isSimulation()) { - game.informPlayer(controller, "Creature should block all attackers if able this turn: " + creature.getIdName()); - } - } else { - Player defender = game.getPlayer(creature.getControllerId()); - if (defender != null) { - for (UUID attackingCreatureId : getAttackers()) { - if (creature.canBlock(attackingCreatureId, game)) { - // ??? - if (attackersToBlock.contains(attackingCreatureId)) { - defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game); - } - } - } - } - } - return false; - } - } - */ } } From 2685d9f8b4740b4743ccf74aa337c3569b6c93a9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 11 Jan 2018 06:12:27 +0100 Subject: [PATCH 62/71] Fixed some possible null pointer exceptions (found in server log). Market Festival, Kindred Summons, Profane Processions, New Blood, Kindred Charge , Bishop of Binding, Metzal Tower of Triumph, Chrome Mox --- .../src/mage/cards/b/BishopOfBinding.java | 8 +++++--- Mage.Sets/src/mage/cards/c/ChromeMox.java | 9 ++++++++- Mage.Sets/src/mage/cards/k/KindredCharge.java | 12 ++++++++---- .../src/mage/cards/k/KindredSummons.java | 19 ++++++++++++------- .../src/mage/cards/m/MarketFestival.java | 11 +++++------ .../mage/cards/m/MetzaliTowerOfTriumph.java | 8 +++++--- Mage.Sets/src/mage/cards/n/NewBlood.java | 8 +++----- .../src/mage/cards/p/ProfaneProcession.java | 2 +- ...tureEntersBattlefieldTriggeredAbility.java | 16 ++++++++-------- .../mage/game/permanent/PermanentImpl.java | 7 +++++++ 10 files changed, 62 insertions(+), 38 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BishopOfBinding.java b/Mage.Sets/src/mage/cards/b/BishopOfBinding.java index 903d923eab7..ea0b73fdd79 100644 --- a/Mage.Sets/src/mage/cards/b/BishopOfBinding.java +++ b/Mage.Sets/src/mage/cards/b/BishopOfBinding.java @@ -132,9 +132,11 @@ class BishopOfBindingExiledCardsPowerCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, sourceAbility.getSourceId(), sourceAbility.getSourceObjectZoneChangeCounter())); - Card exiledCard = exileZone.getRandom(game); - if (exiledCard != null) { - return exiledCard.getPower().getValue(); + if (exileZone != null) { + Card exiledCard = exileZone.getRandom(game); + if (exiledCard != null) { + return exiledCard.getPower().getValue(); + } } return 0; } diff --git a/Mage.Sets/src/mage/cards/c/ChromeMox.java b/Mage.Sets/src/mage/cards/c/ChromeMox.java index 292d9cd2a5b..8358706f9b6 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeMox.java +++ b/Mage.Sets/src/mage/cards/c/ChromeMox.java @@ -182,7 +182,14 @@ class ChromeMoxManaEffect extends ManaEffect { if (choice.getChoices().size() == 1) { choice.setChoice(choice.getChoices().iterator().next()); } else { - player.choose(outcome, choice, game); + while (!player.choose(outcome, choice, game)) { + if (!player.canRespond()) { + return false; + } + } + if (choice.getChoice() == null) { + return false; + } } switch (choice.getChoice()) { case "Black": diff --git a/Mage.Sets/src/mage/cards/k/KindredCharge.java b/Mage.Sets/src/mage/cards/k/KindredCharge.java index 46ef8164c35..fda4299dfb9 100644 --- a/Mage.Sets/src/mage/cards/k/KindredCharge.java +++ b/Mage.Sets/src/mage/cards/k/KindredCharge.java @@ -34,10 +34,10 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.abilities.effects.common.ExileTargetEffect; -import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -57,7 +57,7 @@ public class KindredCharge extends CardImpl { public KindredCharge(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}"); - // Choose a creature type. For each creature you control of the chosen type, create a token that's a copy of that creature. + // Choose a creature type. For each creature you control of the chosen type, create a token that's a copy of that creature. // Those tokens gain haste. Exile them at the beginning of the next end step. this.getSpellAbility().addEffect(new ChooseCreatureTypeEffect(Outcome.Copy)); this.getSpellAbility().addEffect(new KindredChargeEffect()); @@ -95,7 +95,11 @@ class KindredChargeEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (controller != null && sourceObject != null) { - String creatureType = game.getState().getValue(sourceObject.getId() + "_type").toString(); + Object object = game.getState().getValue(sourceObject.getId() + "_type"); + if (object == null) { + return false; + } + String creatureType = object.toString(); FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control of the chosen type"); filter.add(new SubtypePredicate(SubType.byDescription(creatureType))); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/k/KindredSummons.java b/Mage.Sets/src/mage/cards/k/KindredSummons.java index a34f76dc977..5adea872223 100644 --- a/Mage.Sets/src/mage/cards/k/KindredSummons.java +++ b/Mage.Sets/src/mage/cards/k/KindredSummons.java @@ -34,9 +34,9 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.CardType; @@ -48,6 +48,7 @@ import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.players.Player; + /** * * @author Saga @@ -55,10 +56,10 @@ import mage.players.Player; public class KindredSummons extends CardImpl { public KindredSummons(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{5}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{G}{G}"); - // Choose a creature type. Reveal cards from the top of your library until you reveal X creature cards of the chosen type, - // where X is the number of creatures you control of that type. Put those cards onto the battlefield, + // Choose a creature type. Reveal cards from the top of your library until you reveal X creature cards of the chosen type, + // where X is the number of creatures you control of that type. Put those cards onto the battlefield, // then shuffle the rest of the revealed cards into your library. this.getSpellAbility().addEffect(new ChooseCreatureTypeEffect(Outcome.PutCreatureInPlay)); this.getSpellAbility().addEffect(new KindredSummonsEffect()); @@ -78,8 +79,8 @@ class KindredSummonsEffect extends OneShotEffect { public KindredSummonsEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "Reveal cards from the top of your library until you reveal X creature cards of the chosen type, " + - "where X is the number of creatures you control of that type. Put those cards onto the battlefield, " + this.staticText = "Reveal cards from the top of your library until you reveal X creature cards of the chosen type, " + + "where X is the number of creatures you control of that type. Put those cards onto the battlefield, " + "then shuffle the rest of the revealed cards into your library"; } @@ -97,7 +98,11 @@ class KindredSummonsEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (controller != null && sourceObject != null) { - String creatureType = game.getState().getValue(sourceObject.getId() + "_type").toString(); + Object object = game.getState().getValue(sourceObject.getId() + "_type"); + if (object == null) { + return false; + } + String creatureType = object.toString(); FilterControlledCreaturePermanent filterPermanent = new FilterControlledCreaturePermanent("creature you control of the chosen type"); filterPermanent.add(new SubtypePredicate(SubType.byDescription(creatureType))); int numberOfCards = game.getBattlefield().countAll(filterPermanent, source.getControllerId(), game); diff --git a/Mage.Sets/src/mage/cards/m/MarketFestival.java b/Mage.Sets/src/mage/cards/m/MarketFestival.java index c8f0680272a..930a9adb431 100644 --- a/Mage.Sets/src/mage/cards/m/MarketFestival.java +++ b/Mage.Sets/src/mage/cards/m/MarketFestival.java @@ -39,8 +39,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceColor; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; @@ -57,10 +57,9 @@ import mage.target.common.TargetLandPermanent; public class MarketFestival extends CardImpl { public MarketFestival(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); this.subtype.add(SubType.AURA); - // Enchant land TargetPermanent auraTarget = new TargetLandPermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -108,14 +107,12 @@ class MarketFestivalTriggeredAbility extends TriggeredManaAbility { return enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo()); } - @Override public String getRule() { return "Whenever enchanted land is tapped for mana, its controller adds two mana in any combination of colors to his or her mana pool (in addition to the mana the land produces)."; } } - class MarketFestivalManaEffect extends ManaEffect { public MarketFestivalManaEffect() { @@ -152,7 +149,9 @@ class MarketFestivalManaEffect extends ManaEffect { return false; } } - + if (choiceColor.getChoice() == null) { // Possible after reconnect? + return false; + } choiceColor.increaseMana(mana); } checkToFirePossibleEvents(mana, game, source); diff --git a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java index b22efae84d9..b060d0513c6 100644 --- a/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java +++ b/Mage.Sets/src/mage/cards/m/MetzaliTowerOfTriumph.java @@ -126,9 +126,11 @@ class MetzaliTowerOfTriumphEffect extends OneShotEffect { available.add(permanent); } } - Permanent permanent = available.get(RandomUtil.nextInt(available.size())); - if (permanent != null) { - permanent.destroy(source.getSourceId(), game, false); + if (!available.isEmpty()) { + Permanent permanent = available.get(RandomUtil.nextInt(available.size())); + if (permanent != null) { + permanent.destroy(source.getSourceId(), game, false); + } } return true; } diff --git a/Mage.Sets/src/mage/cards/n/NewBlood.java b/Mage.Sets/src/mage/cards/n/NewBlood.java index a6f3905c73e..e65704f83e2 100644 --- a/Mage.Sets/src/mage/cards/n/NewBlood.java +++ b/Mage.Sets/src/mage/cards/n/NewBlood.java @@ -27,6 +27,7 @@ */ package mage.cards.n; +import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; @@ -52,10 +53,6 @@ import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; -import java.util.LinkedHashSet; -import java.util.UUID; -import java.util.stream.Collectors; - /** * * @author LevelX2 @@ -124,7 +121,7 @@ class NewBloodEffect extends OneShotEffect { class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl { private SubType fromSubType; - private SubType toSubType; + private final SubType toSubType; public ChangeCreatureTypeTargetEffect(SubType fromSubType, SubType toSubType, Duration duration) { super(duration, Layer.TextChangingEffects_3, SubLayer.NA, Outcome.Benefit); @@ -153,6 +150,7 @@ class ChangeCreatureTypeTargetEffect extends ContinuousEffectImpl { } } if (typeChoice.getChoice() == null) { + discard(); return; } fromSubType = SubType.byDescription(typeChoice.getChoice()); diff --git a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java index be2b250fcf9..bafe4c068da 100644 --- a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java +++ b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java @@ -105,7 +105,7 @@ class ProfaneProcessionEffect extends OneShotEffect { new ExileTargetEffect(exileId, sourceObject.getIdName()).setTargetPointer(targetPointer).apply(game, source); game.applyEffects(); ExileZone exileZone = game.getExile().getExileZone(exileId); - if (exileZone.size() > 2) { + if (exileZone != null && exileZone.size() > 2) { new TransformSourceEffect(true).apply(game, source); } return true; diff --git a/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java index 3f9f31d2bfd..85b39c3a7d2 100644 --- a/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java @@ -27,11 +27,12 @@ */ package mage.abilities.common; -import mage.constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; @@ -51,7 +52,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI /** * optional = false
* opponentController = false - * + * * @param effect */ public CreatureEntersBattlefieldTriggeredAbility(Effect effect) { @@ -60,7 +61,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI /** * opponentController = false - * + * * @param effect * @param optional */ @@ -69,7 +70,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI } /** - * + * * @param effect * @param optional * @param opponentController @@ -78,7 +79,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI this(Zone.BATTLEFIELD, effect, optional, opponentController); } - + /** * @param zone * @param effect @@ -104,7 +105,6 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI } } - public CreatureEntersBattlefieldTriggeredAbility(CreatureEntersBattlefieldTriggeredAbility ability) { super(ability); this.opponentController = ability.opponentController; @@ -118,7 +118,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI @Override public boolean checkTrigger(GameEvent event, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); + Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); if (filter.match(permanent, sourceId, controllerId, game) && (permanent.getControllerId().equals(this.controllerId) ^ opponentController)) { if (!this.getTargets().isEmpty()) { @@ -137,7 +137,7 @@ public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityI @Override public String getRule() { - return "Whenever a " + filter.getMessage() +" enters the battlefield under " + return "Whenever a " + filter.getMessage() + " enters the battlefield under " + (opponentController ? "an opponent's control, " : "your control, ") + super.getRule(); } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index b97a5af04d8..37111ccd779 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -60,12 +60,15 @@ import mage.target.TargetCard; import mage.util.CardUtil; import mage.util.GameLog; import mage.util.ThreadLocalStringBuilder; +import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com */ public abstract class PermanentImpl extends CardImpl implements Permanent { + private static final Logger logger = Logger.getLogger(PermanentImpl.class); + public class MarkedDamageInfo { public MarkedDamageInfo(Counter counter, MageObject sourceObject) { @@ -699,6 +702,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } } } + if (getSpellAbility() == null) { + logger.info("FATAL : no spell ability for attach to permanent: " + getName()); + return; + } if (!getSpellAbility().getTargets().isEmpty() && (getSpellAbility().getTargets().get(0) instanceof TargetCard)) { Card attachedToCard = game.getCard(this.getAttachedTo()); if (attachedToCard != null) { From 4c9ed95662f936c8859d6f5c1767e22cd1baeef1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 11 Jan 2018 07:14:49 +0100 Subject: [PATCH 63/71] Xmage 1.4.26V11d --- .../src/main/java/mage/utils/MageVersion.java | 2 +- Mage.Sets/src/mage/cards/a/AuraGraft.java | 13 +++++++------ .../java/mage/cards/repository/CardRepository.java | 2 +- Mage/src/main/java/mage/game/combat/Combat.java | 3 +-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java index 4a6adeb7dc4..749041fff54 100644 --- a/Mage.Common/src/main/java/mage/utils/MageVersion.java +++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 26; - public final static String MAGE_VERSION_MINOR_PATCH = "V11c"; + public final static String MAGE_VERSION_MINOR_PATCH = "V11d"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Sets/src/mage/cards/a/AuraGraft.java b/Mage.Sets/src/mage/cards/a/AuraGraft.java index 80970884c70..09cc30a020e 100644 --- a/Mage.Sets/src/mage/cards/a/AuraGraft.java +++ b/Mage.Sets/src/mage/cards/a/AuraGraft.java @@ -57,7 +57,7 @@ import mage.util.TargetAddress; public class AuraGraft extends CardImpl { public AuraGraft(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Gain control of target Aura that's attached to a permanent. Attach it to another permanent it can enchant. FilterPermanent filter = new FilterPermanent("Aura that's attached to a permanent"); @@ -81,7 +81,6 @@ public class AuraGraft extends CardImpl { } } - class AttachedToPermanentPredicate implements ObjectPlayerPredicate> { public AttachedToPermanentPredicate() { @@ -95,6 +94,7 @@ class AttachedToPermanentPredicate implements ObjectPlayerPredicate> { + protected Permanent aura; public PermanentCanBeAttachedToPredicate(Permanent aura) { @@ -102,6 +102,7 @@ class PermanentCanBeAttachedToPredicate implements ObjectPlayerPredicate input, Game game) { Permanent potentialAttachment = input.getObject(); for (TargetAddress addr : TargetAddress.walk(aura)) { @@ -130,7 +131,7 @@ class MoveTargetAuraEffect extends OneShotEffect { } @Override - public boolean apply(Game game, Ability source){ + public boolean apply(Game game, Ability source) { Permanent enchantment = game.getPermanent(targetPointer.getFirst(game, source)); if (enchantment == null) { return false; @@ -150,10 +151,10 @@ class MoveTargetAuraEffect extends OneShotEffect { Target target = new TargetPermanent(filter); target.setNotTarget(true); if (target.canChoose(oldAttachment.getId(), controller.getId(), game) - && controller.choose(outcome, target, oldAttachment.getId(), game)) { + && controller.choose(outcome, target, oldAttachment.getId(), game)) { Permanent newAttachment = game.getPermanent(target.getFirstTarget()); - if (newAttachment != null && - oldAttachment.removeAttachment(enchantment.getId(), game)) { + if (newAttachment != null + && oldAttachment.removeAttachment(enchantment.getId(), game)) { newAttachment.addAttachment(enchantment.getId(), game); game.informPlayers(enchantment.getLogName() + " was unattached from " + oldAttachment.getLogName() + " and attached to " + newAttachment.getLogName()); return true; diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index db9f2bf33f4..857fd8e6b48 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -58,7 +58,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 51; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 99; + private static final long CARD_CONTENT_VERSION = 100; private Dao cardDao; private Set classNames; diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index f6a76d8aefc..617a29c50cb 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -38,7 +38,6 @@ import mage.abilities.keyword.special.JohanVigilanceAbility; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreatureForCombatBlock; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; @@ -655,7 +654,7 @@ public class Combat implements Serializable, Copyable { Map> mustBeBlockedByAtLeastOne = new HashMap<>(); // check mustBlock requirements of creatures from opponents of attacking player - for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), game)) { + for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED, player.getId(), game)) { // creature is controlled by an opponent of the attacker if (opponents.contains(creature.getControllerId())) { From 96e6a917b40e14bc81f7deac206d13b89a0b20bd Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 11 Jan 2018 17:43:33 +1100 Subject: [PATCH 64/71] Add 3 cards (UGL) --- Mage.Sets/src/mage/cards/f/FowlPlay.java | 92 +++++++++++++ Mage.Sets/src/mage/cards/g/GoblinTutor.java | 125 ++++++++++++++++++ .../src/mage/cards/h/HungryHungryHeifer.java | 116 ++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 3 + .../effects/common/DoIfCostPaid.java | 13 +- .../src/main/java/mage/constants/SubType.java | 6 +- 6 files changed, 347 insertions(+), 8 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/f/FowlPlay.java create mode 100644 Mage.Sets/src/mage/cards/g/GoblinTutor.java create mode 100644 Mage.Sets/src/mage/cards/h/HungryHungryHeifer.java diff --git a/Mage.Sets/src/mage/cards/f/FowlPlay.java b/Mage.Sets/src/mage/cards/f/FowlPlay.java new file mode 100644 index 00000000000..1493f8fcda0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FowlPlay.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureAttachedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.permanent.token.Token; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author spjspj + */ +public class FowlPlay extends CardImpl { + + public FowlPlay(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature is a Chicken with base power and toughness 1/1 and loses all abilities. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new BecomesCreatureAttachedEffect(new FowlPlayToken(), + "Enchanted creature is a Chicken with base power and toughness 1/1 and loses all abilities", + Duration.WhileOnBattlefield, BecomesCreatureAttachedEffect.LoseType.ABILITIES_SUBTYPE_AND_PT))); + } + + public FowlPlay(final FowlPlay card) { + super(card); + } + + @Override + public FowlPlay copy() { + return new FowlPlay(this); + } +} + +class FowlPlayToken extends Token { + + public FowlPlayToken() { + super("Chicken", "a Chicken with base power and toughness 1/1 with no abilities"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.CHICKEN); + power = new MageInt(1); + toughness = new MageInt(1); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinTutor.java b/Mage.Sets/src/mage/cards/g/GoblinTutor.java new file mode 100644 index 00000000000..bb6a135605e --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinTutor.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.g; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.filter.common.FilterArtifactCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterEnchantmentCard; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author spjspj + */ +public class GoblinTutor extends CardImpl { + + public GoblinTutor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); + + // Roll a six-sided die. If you roll a 1, Goblin Tutor has no effect. Otherwise, search your library for the indicated card, reveal it, put it into your hand, then shuffle your library. 2 - A card named Goblin Tutor 3 - An enchantment card 4 - An artifact card 5 - A creature card 6 - An instant or sorcery card + this.getSpellAbility().addEffect(new GoblinTutorEffect()); + } + + public GoblinTutor(final GoblinTutor card) { + super(card); + } + + @Override + public GoblinTutor copy() { + return new GoblinTutor(this); + } +} + +class GoblinTutorEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("card named Goblin Tutor"); + + static { + filter.add(new NamePredicate("Goblin Tutor")); + } + + public GoblinTutorEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Roll a six-sided die. If you roll a 1, {this} has no effect. Otherwise, search your library for the indicated card, reveal it, put it into your hand, then shuffle your library. 2 - A card named Goblin Tutor 3 - An enchantment card 4 - An artifact card 5 - A creature card 6 - An instant or sorcery card"; + } + + public GoblinTutorEffect(final GoblinTutorEffect effect) { + super(effect); + } + + @Override + public GoblinTutorEffect copy() { + return new GoblinTutorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int amount = controller.rollDice(game, 6); + + Effect effect = null; + // 2 - A card named Goblin Tutor + // 3 - An enchantment card + // 4 - An artifact card + // 5 - A creature card + // 6 - An instant or sorcery card + if (amount == 2) { + effect = new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, filter), true); + } else if (amount == 3) { + effect = new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, new FilterEnchantmentCard()), true); + } else if (amount == 4) { + effect = new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, new FilterArtifactCard()), true); + } else if (amount == 5) { + effect = new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, new FilterCreatureCard()), true); + } else if (amount == 6) { + effect = new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, new FilterInstantOrSorceryCard()), true); + } + + if (effect != null) { + effect.apply(game, source); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HungryHungryHeifer.java b/Mage.Sets/src/mage/cards/h/HungryHungryHeifer.java new file mode 100644 index 00000000000..40ffa92a0b4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HungryHungryHeifer.java @@ -0,0 +1,116 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.common.RemoveCounterCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author spjspj + */ +public class HungryHungryHeifer extends CardImpl { + + public HungryHungryHeifer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.COW); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // At the beginning of your upkeep, you may remove a counter from a permanent you control. If you don't, sacrifice Hungry Hungry Heifer. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new HungryHungryHeiferEffect(), TargetController.YOU, false, false)); + } + + public HungryHungryHeifer(final HungryHungryHeifer card) { + super(card); + } + + @Override + public HungryHungryHeifer copy() { + return new HungryHungryHeifer(this); + } +} + +class HungryHungryHeiferEffect extends OneShotEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("a permanent you control with a counter on it"); + + static { + filter.add(new CounterPredicate(null)); + } + + public HungryHungryHeiferEffect() { + super(Outcome.Sacrifice); + this.staticText = "you may remove a counter from a permanent you control. If you don't, sacrifice {this}"; + } + + public HungryHungryHeiferEffect(final HungryHungryHeiferEffect effect) { + super(effect); + } + + @Override + public HungryHungryHeiferEffect copy() { + return new HungryHungryHeiferEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourceObject = (Permanent) source.getSourceObjectIfItStillExists(game); + if (sourceObject != null && controller != null) { + if (controller.chooseUse(outcome, "Remove a counter from a permanent you control?", source, game)) { + TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); + RemoveCounterCost cost = new RemoveCounterCost(target); + if (cost.pay(null, game, source.getSourceId(), controller.getId(), true)) { + return true; + } + } + sourceObject.sacrifice(source.getSourceId(), game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index 9e33d2e77c3..e6b503616b6 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -24,7 +24,10 @@ public class Unglued extends ExpansionSet { cards.add(new SetCardInfo("Chicken Egg", 41, Rarity.COMMON, mage.cards.c.ChickenEgg.class)); cards.add(new SetCardInfo("Chicken a la King", 17, Rarity.RARE, mage.cards.c.ChickenALaKing.class)); cards.add(new SetCardInfo("Forest", 88, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("Fowl Play", 24, Rarity.COMMON, mage.cards.f.FowlPlay.class)); + cards.add(new SetCardInfo("Goblin Tutor", 45, Rarity.UNCOMMON, mage.cards.g.GoblinTutor.class)); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); + cards.add(new SetCardInfo("Hungry Hungry Heifer", 63, Rarity.UNCOMMON, mage.cards.h.HungryHungryHeifer.class)); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Jack-in-the-Mox", 75, Rarity.RARE, mage.cards.j.JackInTheMox.class)); cards.add(new SetCardInfo("Jumbo Imp", 34, Rarity.UNCOMMON, mage.cards.j.JumboImp.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java b/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java index c264b34e9d9..bba8baab7f9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DoIfCostPaid.java @@ -36,7 +36,9 @@ public class DoIfCostPaid extends OneShotEffect { public DoIfCostPaid(Effect effect, Cost cost, String chooseUseText, boolean optional) { super(Outcome.Benefit); - this.executingEffects.add(effect); + if (effect != null) { + this.executingEffects.add(effect); + } this.cost = cost; this.chooseUseText = chooseUseText; this.optional = optional; @@ -74,10 +76,9 @@ public class DoIfCostPaid extends OneShotEffect { message = CardUtil.replaceSourceName(message, mageObject.getLogName()); boolean result = true; if (cost.canPay(source, source.getSourceId(), player.getId(), game) - && (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) { + && executingEffects.size() > 0 && (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) { cost.clearPaid(); if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) { - game.applyEffects(); // To end effects e.g. of sacrificed permanents for (Effect effect : executingEffects) { effect.setTargetPointer(this.targetPointer); if (effect instanceof OneShotEffect) { @@ -87,7 +88,8 @@ public class DoIfCostPaid extends OneShotEffect { } } player.resetStoredBookmark(game); // otherwise you can e.g. undo card drawn with Mentor of the Meek - } else if (!otherwiseEffects.isEmpty()) { + } + else if (!otherwiseEffects.isEmpty()) { for (Effect effect : otherwiseEffects) { effect.setTargetPointer(this.targetPointer); if (effect instanceof OneShotEffect) { @@ -97,7 +99,8 @@ public class DoIfCostPaid extends OneShotEffect { } } } - } else if (!otherwiseEffects.isEmpty()) { + } + else if (!otherwiseEffects.isEmpty()) { for (Effect effect : otherwiseEffects) { effect.setTargetPointer(this.targetPointer); if (effect instanceof OneShotEffect) { diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index a893adab284..8ff379718b4 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -85,14 +85,14 @@ public enum SubType { CENTAUR("Centaur", SubTypeSet.CreatureType), CEREAN("Cerean", SubTypeSet.CreatureType, true), // Star Wars CEPHALID("Cephalid", SubTypeSet.CreatureType), - CHICKEN("Chicken", SubTypeSet.CreatureType), // Unglued + CHICKEN("Chicken", SubTypeSet.CreatureType, true), // Unglued CHIMERA("Chimera", SubTypeSet.CreatureType), CHISS("Chiss", SubTypeSet.CreatureType, true), CITIZEN("Citizen", SubTypeSet.CreatureType), CLERIC("Cleric", SubTypeSet.CreatureType), COCKATRICE("Cockatrice", SubTypeSet.CreatureType), CONSTRUCT("Construct", SubTypeSet.CreatureType), - COW("Cow", SubTypeSet.CreatureType), // Unglued + COW("Cow", SubTypeSet.CreatureType, true), // Unglued COWARD("Coward", SubTypeSet.CreatureType), CRAB("Crab", SubTypeSet.CreatureType), CROCODILE("Crocodile", SubTypeSet.CreatureType), @@ -134,7 +134,7 @@ public enum SubType { FROG("Frog", SubTypeSet.CreatureType), FUNGUS("Fungus", SubTypeSet.CreatureType), // G - GAMER("Gamer", SubTypeSet.CreatureType), // Un-sets + GAMER("Gamer", SubTypeSet.CreatureType, true), // Un-sets GAMORREAN("Gamorrean", SubTypeSet.CreatureType, true), // Star Wars GAND("Gand", SubTypeSet.CreatureType, true), // Star Wars GARGOYLE("Gargoyle", SubTypeSet.CreatureType), From 78ac82a2d70da71182db1f9884e41153f17a2e0f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 11 Jan 2018 12:54:09 +0100 Subject: [PATCH 65/71] * See Red - Fixed that it was wrongly sacrificed (fixes #4395). --- Mage.Sets/src/mage/cards/s/SeeRed.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/s/SeeRed.java b/Mage.Sets/src/mage/cards/s/SeeRed.java index 8c827575e1c..7f5ec234b65 100644 --- a/Mage.Sets/src/mage/cards/s/SeeRed.java +++ b/Mage.Sets/src/mage/cards/s/SeeRed.java @@ -52,6 +52,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.watchers.common.AttackedThisTurnWatcher; /** * @@ -82,7 +83,7 @@ public class SeeRed extends CardImpl { this.addAbility(new ConditionalTriggeredAbility( new AtTheBeginOfNextEndStepDelayedTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU), new InvertCondition(ControllerAttackedThisTurnCondition.instance), - "At the beginning of your end step, if you didn't attack with a creature this turn, sacrifice {this}.")); + "At the beginning of your end step, if you didn't attack with a creature this turn, sacrifice {this}."), new AttackedThisTurnWatcher()); } public SeeRed(final SeeRed card) { From 63cb9979420e7c1814d3d5cb672da0cfe1d2063d Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 11 Jan 2018 23:42:52 +1100 Subject: [PATCH 66/71] Add 5 cards (UGL) --- Mage.Sets/src/mage/cards/i/Incoming.java | 121 ++++++++++++++++++ Mage.Sets/src/mage/cards/p/PaperTiger.java | 74 +++++++++++ Mage.Sets/src/mage/cards/r/RockLobster.java | 74 +++++++++++ .../src/mage/cards/s/ScissorsLizard.java | 74 +++++++++++ .../mage/cards/t/TheCheeseStandsAlone.java | 118 +++++++++++++++++ Mage.Sets/src/mage/sets/Unglued.java | 5 + 6 files changed, 466 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/Incoming.java create mode 100644 Mage.Sets/src/mage/cards/p/PaperTiger.java create mode 100644 Mage.Sets/src/mage/cards/r/RockLobster.java create mode 100644 Mage.Sets/src/mage/cards/s/ScissorsLizard.java create mode 100644 Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java diff --git a/Mage.Sets/src/mage/cards/i/Incoming.java b/Mage.Sets/src/mage/cards/i/Incoming.java new file mode 100644 index 00000000000..801a6c24724 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/Incoming.java @@ -0,0 +1,121 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.i; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author spjspj + */ +public class Incoming extends CardImpl { + + public Incoming(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}{G}{G}"); + + // Each player searches his or her library for any number of artifact, creature, enchantment, and/or land cards, puts them onto the battlefield, then shuffles his or her library. + this.getSpellAbility().addEffect(new IncomingEffect()); + } + + public Incoming(final Incoming card) { + super(card); + } + + @Override + public Incoming copy() { + return new Incoming(this); + } +} + +class IncomingEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("artifact, creature, enchantment, and/or land cards"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.ENCHANTMENT), + new CardTypePredicate(CardType.LAND))); + } + + public IncomingEffect() { + super(Outcome.Detriment); + this.staticText = "Each player searches his or her library for any number of artifact, creature, enchantment, and/or land cards, puts them onto the battlefield, then shuffles his or her library"; + } + + public IncomingEffect(final IncomingEffect effect) { + super(effect); + } + + @Override + public IncomingEffect copy() { + return new IncomingEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetCardInLibrary target = new TargetCardInLibrary(0, Integer.MAX_VALUE, filter); + if (player.searchLibrary(target, game)) { + for (UUID cardId : target.getTargets()) { + Card card = player.getLibrary().getCard(cardId, game); + if (card != null) { + card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), player.getId(), true); + } + + } + player.shuffleLibrary(source, game); + } + } + } + // prevent undo + controller.resetStoredBookmark(game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PaperTiger.java b/Mage.Sets/src/mage/cards/p/PaperTiger.java new file mode 100644 index 00000000000..000fd9a900e --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PaperTiger.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackBlockAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; + +/** + * + * @author spjspj + */ +public class PaperTiger extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures named Rock Lobster"); + + static { + filter.add(new NamePredicate("Rock Lobster")); + } + + public PaperTiger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + + this.subtype.add(SubType.CAT); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Creatures named Rock Lobster can't attack or block. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAllEffect(Duration.WhileOnBattlefield, filter))); + } + + public PaperTiger(final PaperTiger card) { + super(card); + } + + @Override + public PaperTiger copy() { + return new PaperTiger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RockLobster.java b/Mage.Sets/src/mage/cards/r/RockLobster.java new file mode 100644 index 00000000000..a33decf378a --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RockLobster.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackBlockAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; + +/** + * + * @author spjspj + */ +public class RockLobster extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures named Scissors Lizard"); + + static { + filter.add(new NamePredicate("Scissors Lizard")); + } + + public RockLobster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + + this.subtype.add(SubType.LOBSTER); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Creatures named Scissors Lizard can't attack or block. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAllEffect(Duration.WhileOnBattlefield, filter))); + } + + public RockLobster(final RockLobster card) { + super(card); + } + + @Override + public RockLobster copy() { + return new RockLobster(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ScissorsLizard.java b/Mage.Sets/src/mage/cards/s/ScissorsLizard.java new file mode 100644 index 00000000000..2bc3a78a851 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScissorsLizard.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackBlockAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; + +/** + * + * @author spjspj + */ +public class ScissorsLizard extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures named Paper Tiger"); + + static { + filter.add(new NamePredicate("Paper Tiger")); + } + + public ScissorsLizard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + + this.subtype.add(SubType.LIZARD); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Creatures named Paper Tiger can't attack or block. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAllEffect(Duration.WhileOnBattlefield, filter))); + } + + public ScissorsLizard(final ScissorsLizard card) { + super(card); + } + + @Override + public ScissorsLizard copy() { + return new ScissorsLizard(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java b/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java new file mode 100644 index 00000000000..2f8b7b80c78 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheCheeseStandsAlone.java @@ -0,0 +1,118 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; + +/** + * + * @author spjspj + */ +public class TheCheeseStandsAlone extends CardImpl { + + public TheCheeseStandsAlone(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}{W}"); + + // When you control no permanents other than The Cheese Stands Alone and have no cards in hand, you win the game. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new CheeseStandsAloneContinuousEffect()); + this.addAbility(ability); + } + + public TheCheeseStandsAlone(final TheCheeseStandsAlone card) { + super(card); + } + + @Override + public TheCheeseStandsAlone copy() { + return new TheCheeseStandsAlone(this); + } +} + +class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + + private boolean wonAlready = false; + static { + filter.add(new NamePredicate("The Cheese Stands Alone")); + } + + public CheeseStandsAloneContinuousEffect() { + super(Duration.EndOfGame, Outcome.Benefit, false, false); + staticText = "When you control no permanents other than {this} and have no cards in hand, you win the game"; + } + + public CheeseStandsAloneContinuousEffect(final CheeseStandsAloneContinuousEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + if (controller.getHand().isEmpty()) { + int numberPerms = new PermanentsOnBattlefieldCount(new FilterControlledPermanent()).calculate(game, source, this); + if (numberPerms == 1) { + if (game.getBattlefield().contains(filter, source.getControllerId(), 1, game)) { + if (!wonAlready) { + wonAlready = true; + controller.won(game); + } + } + } + } + } + return false; + } + + @Override + public CheeseStandsAloneContinuousEffect copy() { + return new CheeseStandsAloneContinuousEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Unglued.java b/Mage.Sets/src/mage/sets/Unglued.java index e6b503616b6..f871f4e32e8 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -28,14 +28,19 @@ public class Unglued extends ExpansionSet { cards.add(new SetCardInfo("Goblin Tutor", 45, Rarity.UNCOMMON, mage.cards.g.GoblinTutor.class)); cards.add(new SetCardInfo("Growth Spurt", 61, Rarity.COMMON, mage.cards.g.GrowthSpurt.class)); cards.add(new SetCardInfo("Hungry Hungry Heifer", 63, Rarity.UNCOMMON, mage.cards.h.HungryHungryHeifer.class)); + cards.add(new SetCardInfo("Incoming!", 64, Rarity.RARE, mage.cards.i.Incoming.class)); cards.add(new SetCardInfo("Island", 85, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Jack-in-the-Mox", 75, Rarity.RARE, mage.cards.j.JackInTheMox.class)); cards.add(new SetCardInfo("Jumbo Imp", 34, Rarity.UNCOMMON, mage.cards.j.JumboImp.class)); cards.add(new SetCardInfo("Krazy Kow", 48, Rarity.COMMON, mage.cards.k.KrazyKow.class)); cards.add(new SetCardInfo("Mountain", 87, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("Paper Tiger", 78, Rarity.COMMON, mage.cards.p.PaperTiger.class)); cards.add(new SetCardInfo("Plains", 84, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Poultrygeist", 37, Rarity.COMMON, mage.cards.p.Poultrygeist.class)); + cards.add(new SetCardInfo("Rock Lobster", 79, Rarity.COMMON, mage.cards.r.RockLobster.class)); + cards.add(new SetCardInfo("Scissors Lizard", 80, Rarity.COMMON, mage.cards.s.ScissorsLizard.class)); cards.add(new SetCardInfo("Swamp", 86, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UGL_FULL_ART_BASIC, false))); + cards.add(new SetCardInfo("The Cheese Stands Alone", 2, Rarity.RARE, mage.cards.t.TheCheeseStandsAlone.class)); cards.add(new SetCardInfo("Timmy, Power Gamer", 68, Rarity.RARE, mage.cards.t.TimmyPowerGamer.class)); } } From d9bcfa3f31b78af63358fc3c19191f6fddaa251b Mon Sep 17 00:00:00 2001 From: spjspj Date: Thu, 11 Jan 2018 23:55:37 +1100 Subject: [PATCH 67/71] Add 5 cards (UGL) --- Mage/src/main/java/mage/constants/SubType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 8ff379718b4..e700b9d4f90 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -198,6 +198,7 @@ public enum SubType { LHURGOYF("Lhurgoyf", SubTypeSet.CreatureType), LICID("Licid", SubTypeSet.CreatureType), LIZARD("Lizard", SubTypeSet.CreatureType), + LOBSTER("Lobster", SubTypeSet.CreatureType, true), // Unglued // M MANTELLIAN("Mantellian", SubTypeSet.CreatureType, true), // Star Wars MANTICORE("Manticore", SubTypeSet.CreatureType), From 0ba2375ac13de879d5d99bd3be887b5812ba8b9a Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Thu, 11 Jan 2018 20:37:38 +0400 Subject: [PATCH 68/71] Tests: * added new checks for basic land types/rarity in mage-verify; * fixed tests for UGL cards in mage-verify (wrong json data) --- .../java/mage/verify/VerifyCardDataTest.java | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index a915fb1f09d..a3df908f985 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -4,6 +4,8 @@ import mage.ObjectColor; import mage.cards.*; import mage.cards.basiclands.BasicLand; import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.SuperType; import org.junit.Assert; import org.junit.Test; @@ -30,6 +32,12 @@ public class VerifyCardDataTest { static { // skip lists for checks (example: unstable cards with same name may have different stats) + // TODO: mtgjson have wrong data for UGL + // remove after fixed + // https://github.com/mtgjson/mtgjson/issues/531 + // https://github.com/mtgjson/mtgjson/issues/534 + // https://github.com/mtgjson/mtgjson/issues/535 + // power-toughness skipListCreate("PT"); skipListAddName("PT", "Garbage Elemental"); // UST @@ -37,19 +45,25 @@ public class VerifyCardDataTest { // color skipListCreate("COLOR"); - //skipListAddName("COLOR", "Ulrich, Uncontested Alpha"); // gatherer is missing the color indicator on one card and json has wrong data (16.12.2017: not actual) // cost skipListCreate("COST"); // supertype skipListCreate("SUPERTYPE"); + skipListAddName("SUPERTYPE", "Timmy, Power Gamer"); // UGL, mtgjson error // type skipListCreate("TYPE"); + skipListAddName("TYPE", "Fowl Play"); // UGL, mtgjson error // subtype skipListCreate("SUBTYPE"); + skipListAddName("SUBTYPE", "Timmy, Power Gamer"); // UGL, mtgjson error + skipListAddName("SUBTYPE", "Fowl Play"); // UGL, mtgjson error + skipListAddName("SUBTYPE", "Paper Tiger"); // UGL, mtgjson error + skipListAddName("SUBTYPE", "Rock Lobster"); // UGL, mtgjson error + skipListAddName("SUBTYPE", "Scissors Lizard"); // UGL, mtgjson error // number skipListCreate("NUMBER"); @@ -76,7 +90,7 @@ public class VerifyCardDataTest { private void fail(Card card, String category, String message) { failed++; - System.out.println("Error: (" + category + ") " + message + " for " + card.getName()); + System.out.println("Error: (" + category + ") " + message + " for " + card.getName() + " (" + card.getExpansionSetCode() + ")"); } private int failed = 0; @@ -280,6 +294,7 @@ public class VerifyCardDataTest { checkTypes(card, ref); checkColors(card, ref); //checkNumbers(card, ref); // TODO: load data from allsets.json and check it (allcards.json do not have card numbers) + checkBasicLands(card, ref); } private void checkColors(Card card, JsonCard ref) { @@ -393,6 +408,48 @@ public class VerifyCardDataTest { } } + private boolean isBasicLandName(String name) { + + String checkName = name; + if (name.startsWith("Snow-Covered ")) { + // snow lands is basic lands too + checkName = name.replace("Snow-Covered ", ""); + } + + return checkName.equals("Island") || + checkName.equals("Forest") || + checkName.equals("Swamp") || + checkName.equals("Plains") || + checkName.equals("Mountain") || + checkName.equals("Wastes"); + } + + private void checkBasicLands(Card card, JsonCard ref) { + + // basic lands must have Rarity.LAND and SuperType.BASIC + // other cards can't have that stats + + if (isBasicLandName(card.getName())) { + // lands + if (card.getRarity() != Rarity.LAND) { + fail(card, "rarity", "basic land must be Rarity.LAND"); + } + + if (!card.getSuperType().contains(SuperType.BASIC)) { + fail(card, "supertype", "basic land must be SuperType.BASIC"); + } + } else { + // non lands + if (card.getRarity() == Rarity.LAND) { + fail(card, "rarity", "only basic land can be Rarity.LAND"); + } + + if (card.getSuperType().contains(SuperType.BASIC)) { + fail(card, "supertype", "only basic land can be SuperType.BASIC"); + } + } + } + private String join(Iterable items) { StringBuilder result = new StringBuilder(); for (Object item : items) { From 3632d7afe3c3c1cfc6e0c84fee72295067e1dc4f Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Thu, 11 Jan 2018 20:46:39 +0400 Subject: [PATCH 69/71] Fixed 27 wrong land types (can't see or too many in boosters): * e.g. Urza's lands counts as basic; * Arabian Nights: x1 * Coldsnap: x5 * Ice Age: x5 * Masters Edition IV: x12 * Oath of the Gatewatch: x4 --- Mage.Sets/src/mage/sets/ArabianNights.java | 2 +- Mage.Sets/src/mage/sets/Coldsnap.java | 10 ++++---- Mage.Sets/src/mage/sets/IceAge.java | 10 ++++---- Mage.Sets/src/mage/sets/MastersEditionIV.java | 24 +++++++++---------- .../src/mage/sets/OathOfTheGatewatch.java | 8 +++---- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Mage.Sets/src/mage/sets/ArabianNights.java b/Mage.Sets/src/mage/sets/ArabianNights.java index eb76776430a..ea52d56edc4 100644 --- a/Mage.Sets/src/mage/sets/ArabianNights.java +++ b/Mage.Sets/src/mage/sets/ArabianNights.java @@ -119,7 +119,7 @@ public class ArabianNights extends ExpansionSet { cards.add(new SetCardInfo("Mijae Djinn", 51, Rarity.RARE, mage.cards.m.MijaeDjinn.class)); cards.add(new SetCardInfo("Moorish Cavalry", 62, Rarity.COMMON, mage.cards.m.MoorishCavalry.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Moorish Cavalry", 63, Rarity.COMMON, mage.cards.m.MoorishCavalry.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 91, Rarity.COMMON, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 91, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nafs Asp", 36, Rarity.COMMON, NafsAsp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nafs Asp", 37, Rarity.COMMON, NafsAsp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Oasis", 92, Rarity.UNCOMMON, mage.cards.o.Oasis.class)); diff --git a/Mage.Sets/src/mage/sets/Coldsnap.java b/Mage.Sets/src/mage/sets/Coldsnap.java index fd5daa98b1e..e66a4aeb68a 100644 --- a/Mage.Sets/src/mage/sets/Coldsnap.java +++ b/Mage.Sets/src/mage/sets/Coldsnap.java @@ -170,11 +170,11 @@ public class Coldsnap extends ExpansionSet { cards.add(new SetCardInfo("Sheltering Ancient", 121, Rarity.UNCOMMON, mage.cards.s.ShelteringAncient.class)); cards.add(new SetCardInfo("Simian Brawler", 122, Rarity.COMMON, mage.cards.s.SimianBrawler.class)); cards.add(new SetCardInfo("Skred", 97, Rarity.COMMON, mage.cards.s.Skred.class)); - cards.add(new SetCardInfo("Snow-Covered Forest", 155, Rarity.COMMON, mage.cards.s.SnowCoveredForest.class)); - cards.add(new SetCardInfo("Snow-Covered Island", 152, Rarity.COMMON, mage.cards.s.SnowCoveredIsland.class)); - cards.add(new SetCardInfo("Snow-Covered Mountain", 154, Rarity.COMMON, mage.cards.s.SnowCoveredMountain.class)); - cards.add(new SetCardInfo("Snow-Covered Plains", 151, Rarity.COMMON, mage.cards.s.SnowCoveredPlains.class)); - cards.add(new SetCardInfo("Snow-Covered Swamp", 153, Rarity.COMMON, mage.cards.s.SnowCoveredSwamp.class)); + cards.add(new SetCardInfo("Snow-Covered Forest", 155, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); + cards.add(new SetCardInfo("Snow-Covered Island", 152, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class)); + cards.add(new SetCardInfo("Snow-Covered Mountain", 154, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class)); + cards.add(new SetCardInfo("Snow-Covered Plains", 151, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class)); + cards.add(new SetCardInfo("Snow-Covered Swamp", 153, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class)); cards.add(new SetCardInfo("Soul Spike", 70, Rarity.RARE, mage.cards.s.SoulSpike.class)); cards.add(new SetCardInfo("Sound the Call", 123, Rarity.COMMON, mage.cards.s.SoundTheCall.class)); cards.add(new SetCardInfo("Squall Drifter", 17, Rarity.COMMON, mage.cards.s.SquallDrifter.class)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index 1e47953dc1e..ed0abad5112 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -287,11 +287,11 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Skeleton Ship", 379, Rarity.RARE, mage.cards.s.SkeletonShip.class)); cards.add(new SetCardInfo("Skull Catapult", 311, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class)); cards.add(new SetCardInfo("Snow Fortress", 312, Rarity.RARE, mage.cards.s.SnowFortress.class)); - cards.add(new SetCardInfo("Snow-Covered Forest", 347, Rarity.COMMON, mage.cards.s.SnowCoveredForest.class)); - cards.add(new SetCardInfo("Snow-Covered Island", 348, Rarity.COMMON, mage.cards.s.SnowCoveredIsland.class)); - cards.add(new SetCardInfo("Snow-Covered Mountain", 349, Rarity.COMMON, mage.cards.s.SnowCoveredMountain.class)); - cards.add(new SetCardInfo("Snow-Covered Plains", 350, Rarity.COMMON, mage.cards.s.SnowCoveredPlains.class)); - cards.add(new SetCardInfo("Snow-Covered Swamp", 351, Rarity.COMMON, mage.cards.s.SnowCoveredSwamp.class)); + cards.add(new SetCardInfo("Snow-Covered Forest", 347, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); + cards.add(new SetCardInfo("Snow-Covered Island", 348, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class)); + cards.add(new SetCardInfo("Snow-Covered Mountain", 349, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class)); + cards.add(new SetCardInfo("Snow-Covered Plains", 350, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class)); + cards.add(new SetCardInfo("Snow-Covered Swamp", 351, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class)); cards.add(new SetCardInfo("Snow Hound", 277, Rarity.UNCOMMON, mage.cards.s.SnowHound.class)); cards.add(new SetCardInfo("Soldevi Golem", 313, Rarity.RARE, mage.cards.s.SoldeviGolem.class)); cards.add(new SetCardInfo("Soldevi Machinist", 102, Rarity.UNCOMMON, mage.cards.s.SoldeviMachinist.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionIV.java b/Mage.Sets/src/mage/sets/MastersEditionIV.java index 9357961a62c..10af1532cec 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionIV.java +++ b/Mage.Sets/src/mage/sets/MastersEditionIV.java @@ -279,19 +279,19 @@ public class MastersEditionIV extends ExpansionSet { cards.add(new SetCardInfo("Two-Headed Giant of Foriys", 139, Rarity.UNCOMMON, mage.cards.t.TwoHeadedGiantOfForiys.class)); cards.add(new SetCardInfo("Underground Sea", 256, Rarity.RARE, mage.cards.u.UndergroundSea.class)); cards.add(new SetCardInfo("Urza's Chalice", 236, Rarity.COMMON, mage.cards.u.UrzasChalice.class)); - cards.add(new SetCardInfo("Urza's Mine", "257a", Rarity.LAND, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Mine", "257b", Rarity.LAND, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Mine", "257c", Rarity.LAND, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Mine", "257d", Rarity.LAND, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", "257a", Rarity.COMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", "257b", Rarity.COMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", "257c", Rarity.COMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", "257d", Rarity.COMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Urza's Miter", 237, Rarity.RARE, mage.cards.u.UrzasMiter.class)); - cards.add(new SetCardInfo("Urza's Power Plant", "258a", Rarity.LAND, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", "258b", Rarity.LAND, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", "258c", Rarity.LAND, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", "258d", Rarity.LAND, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", "259a", Rarity.LAND, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", "259b", Rarity.LAND, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", "259c", Rarity.LAND, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", "259d", Rarity.LAND, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", "258a", Rarity.COMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", "258b", Rarity.COMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", "258c", Rarity.COMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", "258d", Rarity.COMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", "259a", Rarity.COMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", "259b", Rarity.COMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", "259c", Rarity.COMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", "259d", Rarity.COMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Veteran Bodyguard", 32, Rarity.RARE, mage.cards.v.VeteranBodyguard.class)); cards.add(new SetCardInfo("Vibrating Sphere", 238, Rarity.RARE, mage.cards.v.VibratingSphere.class)); cards.add(new SetCardInfo("Volcanic Island", 260, Rarity.RARE, mage.cards.v.VolcanicIsland.class)); diff --git a/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java b/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java index 7f6dec55f62..30fe536acc6 100644 --- a/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java +++ b/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java @@ -218,10 +218,10 @@ public class OathOfTheGatewatch extends ExpansionSet { cards.add(new SetCardInfo("Wandering Fumarole", 182, Rarity.RARE, mage.cards.w.WanderingFumarole.class)); cards.add(new SetCardInfo("Warden of Geometries", 11, Rarity.COMMON, mage.cards.w.WardenOfGeometries.class)); cards.add(new SetCardInfo("Warping Wail", 12, Rarity.UNCOMMON, mage.cards.w.WarpingWail.class)); - cards.add(new SetCardInfo("Wastes", "183a", Rarity.COMMON, Wastes.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Wastes", "183b", Rarity.COMMON, Wastes.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Wastes", "184a", Rarity.COMMON, Wastes.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Wastes", "184b", Rarity.COMMON, Wastes.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Wastes", "183a", Rarity.LAND, Wastes.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Wastes", "183b", Rarity.LAND, Wastes.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Wastes", "184a", Rarity.LAND, Wastes.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Wastes", "184b", Rarity.LAND, Wastes.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Weapons Trainer", 160, Rarity.UNCOMMON, mage.cards.w.WeaponsTrainer.class)); cards.add(new SetCardInfo("Witness the End", 82, Rarity.COMMON, mage.cards.w.WitnessTheEnd.class)); cards.add(new SetCardInfo("World Breaker", 126, Rarity.MYTHIC, mage.cards.w.WorldBreaker.class)); From 25072be3062ef8d54bb4bde191c103ba0530c9a2 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Thu, 11 Jan 2018 20:56:24 +0400 Subject: [PATCH 70/71] * Expel from Orazca - Fixed wrong name --- Mage.Sets/src/mage/sets/RivalsOfIxalan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 3589deae5bb..a6497d7d6fa 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -110,7 +110,7 @@ public class RivalsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Etali, Primal Storm", 100, Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class)); cards.add(new SetCardInfo("Everdawn Champion", 6, Rarity.UNCOMMON, mage.cards.e.EverdawnChampion.class)); cards.add(new SetCardInfo("Evolving Wilds", 186, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); - cards.add(new SetCardInfo("Expel From Orazca", 37, Rarity.UNCOMMON, mage.cards.e.ExpelFromOrazca.class)); + cards.add(new SetCardInfo("Expel from Orazca", 37, Rarity.UNCOMMON, mage.cards.e.ExpelFromOrazca.class)); cards.add(new SetCardInfo("Exultant Skymarcher", 7, Rarity.COMMON, mage.cards.e.ExultantSkymarcher.class)); cards.add(new SetCardInfo("Famished Paladin", 8, Rarity.UNCOMMON, mage.cards.f.FamishedPaladin.class)); cards.add(new SetCardInfo("Fanatical Firebrand", 101, Rarity.COMMON, mage.cards.f.FanaticalFirebrand.class)); From 50a906072e0b2c1087021206f4241f14e164c864 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Thu, 11 Jan 2018 21:03:11 +0400 Subject: [PATCH 71/71] * HASCON Promo 2017 - Fixed image downloading for Grimlock cards --- Mage.Sets/src/mage/sets/HasconPromo2017.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/HasconPromo2017.java b/Mage.Sets/src/mage/sets/HasconPromo2017.java index 6ceec640ac7..f1392050cf0 100644 --- a/Mage.Sets/src/mage/sets/HasconPromo2017.java +++ b/Mage.Sets/src/mage/sets/HasconPromo2017.java @@ -45,8 +45,8 @@ public class HasconPromo2017 extends ExpansionSet { private HasconPromo2017() { super("HASCON Promo 2017", "H17", ExpansionSet.buildDate(2017, 9, 8), SetType.JOKESET); - cards.add(new ExpansionSet.SetCardInfo("Grimlock, Dinobot Leader", 1, Rarity.MYTHIC, mage.cards.g.GrimlockDinobotLeader.class)); - cards.add(new ExpansionSet.SetCardInfo("Grimlock, Ferocious King", 1, Rarity.MYTHIC, mage.cards.g.GrimlockFerociousKing.class)); + cards.add(new ExpansionSet.SetCardInfo("Grimlock, Dinobot Leader", "1a", Rarity.MYTHIC, mage.cards.g.GrimlockDinobotLeader.class)); + cards.add(new ExpansionSet.SetCardInfo("Grimlock, Ferocious King", "1b", Rarity.MYTHIC, mage.cards.g.GrimlockFerociousKing.class)); cards.add(new ExpansionSet.SetCardInfo("Sword of Dungeons & Dragons", 3, Rarity.MYTHIC, mage.cards.s.SwordOfDungeonsAndDragons.class)); } }