diff --git a/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java b/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java new file mode 100644 index 0000000000..c346be1d1a --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java @@ -0,0 +1,104 @@ + +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.condition.common.IsStepCondition; +import mage.abilities.costs.CompositeCost; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.RevealSourceFromYourHandCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponentOrPlaneswalker; + +/** + * + * @author Ketsuban + */ +public final class InfernalSpawnOfEvil extends CardImpl { + + public InfernalSpawnOfEvil(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{6}{B}{B}{B}"); + this.subtype.add(SubType.BEAST); + + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // 1B, Reveal Infernal Spawn of Evil from your hand, Say "It's coming!": + // Infernal Spawn of Evil deals 1 damage to target opponent or planeswalker. + // Activate this ability only during your upkeep and only once each turn. + Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.HAND, new DamageTargetEffect(1), + new CompositeCost( + new ManaCostsImpl("{1}{B}"), + new CompositeCost( + new RevealSourceFromYourHandCost(), + new SayCost("It's coming!"), + "Reveal {this} from your hand, Say \"It's coming!\""), + "{1}{B}, Reveal {this} from your hand, Say \"It's coming!\""), + 1, new IsStepCondition(PhaseStep.UPKEEP, true)); + ability.addTarget(new TargetOpponentOrPlaneswalker()); + this.addAbility(ability); + } + + public InfernalSpawnOfEvil(final InfernalSpawnOfEvil card) { + super(card); + } + + @Override + public InfernalSpawnOfEvil copy() { + return new InfernalSpawnOfEvil(this); + } +} + +class SayCost extends CostImpl { + + private String message; + + public SayCost(String message) { + this.message = message; + } + + public SayCost(SayCost cost) { + super(cost); + this.message = cost.message; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + return true; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Player controller = game.getPlayer(controllerId); + if (controller == null) { + return false; + } + game.informPlayers(controller.getLogName() + ": " + message); + return true; + } + + @Override + public Cost copy() { + return new SayCost(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MissDemeanor.java b/Mage.Sets/src/mage/cards/m/MissDemeanor.java new file mode 100644 index 0000000000..e262d64ff8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MissDemeanor.java @@ -0,0 +1,87 @@ + +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FirstStrikeAbility; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author Ketsuban + */ +public final class MissDemeanor extends CardImpl { + + public MissDemeanor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.LADYOFPROPERETIQUETTE); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // At the beginning of each other player's upkeep, you may compliment that player on their game play. If you don't, sacrifice Miss Demeanour. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new MissDemeanorEffect(), TargetController.NOT_YOU, false, true)); + } + + public MissDemeanor(final MissDemeanor card) { + super(card); + } + + @Override + public MissDemeanor copy() { + return new MissDemeanor(this); + } +} + +class MissDemeanorEffect extends OneShotEffect { + + public MissDemeanorEffect() { + super(Outcome.Sacrifice); + this.staticText = "you may compliment that player on their game play. If you don't, sacrifice {this}"; + } + + public MissDemeanorEffect(final MissDemeanorEffect effect) { + super(effect); + } + + @Override + public MissDemeanorEffect copy() { + return new MissDemeanorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourceObject = (Permanent) source.getSourceObjectIfItStillExists(game); + String activePlayerName = game.getPlayer(game.getActivePlayerId()).getName(); + if (sourceObject != null) { + if (controller.chooseUse(outcome, "Compliment " + activePlayerName + " on their game play?", source, game)) { + // TODO(Ketsuban): this could probably stand to be randomly chosen from a pool of compliments + game.informPlayers(controller.getLogName() + ": That's a well-built deck and you pilot it well, " + activePlayerName + "."); + } else { + 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 b432e5833f..bfda5c412e 100644 --- a/Mage.Sets/src/mage/sets/Unglued.java +++ b/Mage.Sets/src/mage/sets/Unglued.java @@ -39,12 +39,14 @@ public final class Unglued extends ExpansionSet { 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("Infernal Spawn of Evil", 33, Rarity.RARE, mage.cards.i.InfernalSpawnOfEvil.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("Jalum Grifter", 47, Rarity.RARE, mage.cards.j.JalumGrifter.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("Mine, Mine, Mine!", 65, Rarity.RARE, mage.cards.m.MineMineMine.class)); + cards.add(new SetCardInfo("Miss Demeanor", 10, Rarity.UNCOMMON, mage.cards.m.MissDemeanor.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("Once More with Feeling", 11, Rarity.RARE, mage.cards.o.OnceMoreWithFeeling.class)); cards.add(new SetCardInfo("Paper Tiger", 78, Rarity.COMMON, mage.cards.p.PaperTiger.class)); diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index d2656c2a4d..3e6594dbd1 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -87,6 +87,7 @@ public class VerifyCardDataTest { // subtype skipListCreate("SUBTYPE"); + skipListAddName("SUBTYPE", "UGL", "Miss Demeanor"); // number skipListCreate("NUMBER"); diff --git a/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java index 49d7c0a70e..87ed534a99 100644 --- a/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BeginningOfUpkeepTriggeredAbility.java @@ -70,6 +70,16 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl { } } return yours; + case NOT_YOU: + boolean notYours = !event.getPlayerId().equals(this.controllerId); + if (notYours && setTargetPointer) { + if (getTargets().isEmpty()) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + } + } + } + return notYours; case OPPONENT: if (game.getPlayer(this.controllerId).hasOpponent(event.getPlayerId(), game)) { if (setTargetPointer && getTargets().isEmpty()) { diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 522cc4bde9..00387a9761 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -201,6 +201,7 @@ public enum SubType { KOR("Kor", SubTypeSet.CreatureType), KRAKEN("Kraken", SubTypeSet.CreatureType), // L + LADYOFPROPERETIQUETTE("Lady of Proper Etiquette", SubTypeSet.CreatureType, true), // Unglued LAMIA("Lamia", SubTypeSet.CreatureType), LAMMASU("Lammasu", SubTypeSet.CreatureType), LEECH("Leech", SubTypeSet.CreatureType),