diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt index d6fb91a0d8..bdb9410a86 100644 --- a/Mage.Client/src/main/resources/card-pictures-tok.txt +++ b/Mage.Client/src/main/resources/card-pictures-tok.txt @@ -187,6 +187,7 @@ |Generate|TOK:ALL|Graveborn|||SekKuarDeathkeeperGravebornToken| |Generate|TOK:ALL|Hippo|||HippoToken| |Generate|TOK:ALL|Soldier|||SoldierToken| +|Generate|TOK:ALL|Starfish|||StarfishToken| |Generate|TOK:ALL|Zombie|||ZombieToken| |Generate|TOK:APC|Angel|||HauntedAngelToken| |Generate|TOK:APC|Cat|||PenumbraBobcatToken| diff --git a/Mage.Sets/src/mage/cards/s/SpinyStarfish.java b/Mage.Sets/src/mage/cards/s/SpinyStarfish.java new file mode 100644 index 0000000000..c2760bd321 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpinyStarfish.java @@ -0,0 +1,157 @@ +package mage.cards.s; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.StarfishToken; +import mage.watchers.Watcher; + +/** + * @author spike + */ +public final class SpinyStarfish extends CardImpl { + + public SpinyStarfish(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.subtype.add(SubType.STARFISH); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // {U}: Regenerate Spiny Starfish. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{U}"))); + + // At the beginning of each end step, if Spiny Starfish regenerated this turn, create a 0/1 blue Starfish creature token for each time it regenerated this turn. + this.addAbility( + new ConditionalInterveningIfTriggeredAbility( + new BeginningOfEndStepTriggeredAbility( + new CreateTokenEffect( + new StarfishToken(), + new SpinyStarfishDynamicValue()), + TargetController.ANY, + false), + SpinyStarfishCondition.instance, + "At the beginning of each end step, if {this} regenerated this turn, create a 0/1 blue Starfish creature token for each time it regenerated this turn."), + new SpinyStarfishWatcher()); + } + + public SpinyStarfish(final SpinyStarfish card) { + super(card); + } + + @Override + public SpinyStarfish copy() { + return new SpinyStarfish(this); + } +} + +enum SpinyStarfishCondition implements Condition { + + instance; + + @Override + public boolean apply(Game game, Ability source) { + SpinyStarfishWatcher watcher = (SpinyStarfishWatcher) game.getState().getWatchers().get(SpinyStarfishWatcher.class.getSimpleName()); + return watcher != null && watcher.regeneratedCount(source.getSourceId()) != 0; + } + + @Override + public String toString() { + return "if Spiny Starfish regenerated this turn"; + } + +} + +class SpinyStarfishWatcher extends Watcher { + + // Probably dumb to record all regeneration events, could just record this, + // but not sure how to know what source this watcher is attached to. + private final Map regeneratedCount = new HashMap<>(); + + public SpinyStarfishWatcher() { + super(SpinyStarfishWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public SpinyStarfishWatcher(final SpinyStarfishWatcher watcher) { + super(watcher); + this.regeneratedCount.putAll(watcher.regeneratedCount); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.REGENERATED) { + UUID regeneratedId = event.getTargetId(); + Integer count = regeneratedCount.get(regeneratedId); + if (count == null) { + count = 0; + } + regeneratedCount.put(regeneratedId, ++count); + } + } + + @Override + public void reset() { + super.reset(); + regeneratedCount.clear(); + } + + public int regeneratedCount(UUID sourceId) { + Integer count = regeneratedCount.get(sourceId); + if (count == null) { + return 0; + } + return count; + } + + @Override + public SpinyStarfishWatcher copy() { + return new SpinyStarfishWatcher(this); + } +} + +class SpinyStarfishDynamicValue implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + SpinyStarfishWatcher watcher = (SpinyStarfishWatcher) game.getState().getWatchers().get( + SpinyStarfishWatcher.class.getSimpleName()); + if (watcher != null) { + return watcher.regeneratedCount(sourceAbility.getSourceId()); + } + return 0; + } + + @Override + public SpinyStarfishDynamicValue copy() { + return new SpinyStarfishDynamicValue(); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "time {this} regenerated this turn"; + } +} diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index e53b14b61d..7df01628f9 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -155,6 +155,7 @@ public final class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Soldevi Steam Beast", "133a", Rarity.COMMON, mage.cards.s.SoldeviSteamBeast.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Soldevi Steam Beast", "133b", Rarity.COMMON, mage.cards.s.SoldeviSteamBeast.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Soldier of Fortune", 80, Rarity.UNCOMMON, mage.cards.s.SoldierOfFortune.class)); + cards.add(new SetCardInfo("Spiny Starfish", 35, Rarity.UNCOMMON, mage.cards.s.SpinyStarfish.class)); cards.add(new SetCardInfo("Stench of Decay", "61a", Rarity.COMMON, mage.cards.s.StenchOfDecay.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Stench of Decay", "61b", Rarity.COMMON, mage.cards.s.StenchOfDecay.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Storm Cauldron", 134, Rarity.RARE, mage.cards.s.StormCauldron.class)); diff --git a/Mage/src/main/java/mage/game/permanent/token/StarfishToken.java b/Mage/src/main/java/mage/game/permanent/token/StarfishToken.java new file mode 100644 index 0000000000..3e2b867fb3 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/StarfishToken.java @@ -0,0 +1,34 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * + * @author spike + */ +public final class StarfishToken extends TokenImpl { + + public StarfishToken() { + this(null, 0); + } + + public StarfishToken(String setCode, int tokenType) { + super("Starfish", "0/1 blue Starfish creature token"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.STARFISH); + color.setBlue(true); + power = new MageInt(0); + toughness = new MageInt(1); + } + + public StarfishToken(final StarfishToken token) { + super(token); + } + + @Override + public StarfishToken copy() { + return new StarfishToken(this); + } +} \ No newline at end of file