From 176f06c1dccf21088e2b2c4b72de15df1248050d Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sat, 4 Apr 2020 22:32:47 -0400 Subject: [PATCH] Implemented Jirina Kudro --- Mage.Sets/src/mage/cards/j/JirinaKudro.java | 55 +++++++++++++++++++ .../src/mage/sets/Commander2020Edition.java | 1 + .../common/CommanderCastCountValue.java | 35 ++++++++++++ .../keyword/CommanderStormAbility.java | 38 +++++++------ .../common/CommanderPlaysCountWatcher.java | 37 +++++++------ 5 files changed, 134 insertions(+), 32 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/j/JirinaKudro.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastCountValue.java diff --git a/Mage.Sets/src/mage/cards/j/JirinaKudro.java b/Mage.Sets/src/mage/cards/j/JirinaKudro.java new file mode 100644 index 00000000000..93fb8d661f0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JirinaKudro.java @@ -0,0 +1,55 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.CommanderCastCountValue; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.permanent.token.HumanSoldierToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JirinaKudro extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.HUMAN, "Humans"); + + public JirinaKudro(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{W}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Jirina Kudro enters the battlefield, create a 1/1 white Human Soldier creature token for each time you've cast a commander from the command zone this game. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect( + new HumanSoldierToken(), CommanderCastCountValue.instance + ))); + + // Other Humans you control get +2/+0. + this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( + 2, 0, Duration.WhileOnBattlefield, filter, true + ))); + } + + private JirinaKudro(final JirinaKudro card) { + super(card); + } + + @Override + public JirinaKudro copy() { + return new JirinaKudro(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Commander2020Edition.java b/Mage.Sets/src/mage/sets/Commander2020Edition.java index 6a9513bca88..25a22af902b 100644 --- a/Mage.Sets/src/mage/sets/Commander2020Edition.java +++ b/Mage.Sets/src/mage/sets/Commander2020Edition.java @@ -29,6 +29,7 @@ public final class Commander2020Edition extends ExpansionSet { cards.add(new SetCardInfo("Deadly Tempest", 131, Rarity.RARE, mage.cards.d.DeadlyTempest.class)); cards.add(new SetCardInfo("Flawless Maneuver", 26, Rarity.RARE, mage.cards.f.FlawlessManeuver.class)); cards.add(new SetCardInfo("Jace, Architect of Thought", 114, Rarity.MYTHIC, mage.cards.j.JaceArchitectOfThought.class)); + cards.add(new SetCardInfo("Jirina Kudro", 8, Rarity.MYTHIC, mage.cards.j.JirinaKudro.class)); cards.add(new SetCardInfo("Kathril, Aspect Warper", 10, Rarity.MYTHIC, mage.cards.k.KathrilAspectWarper.class)); cards.add(new SetCardInfo("Lifecrafter's Bestiary", 244, Rarity.RARE, mage.cards.l.LifecraftersBestiary.class)); cards.add(new SetCardInfo("Masked Admirers", 163, Rarity.RARE, mage.cards.m.MaskedAdmirers.class)); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastCountValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastCountValue.java new file mode 100644 index 00000000000..652bb4bb2db --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastCountValue.java @@ -0,0 +1,35 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.game.Game; +import mage.watchers.common.CommanderPlaysCountWatcher; + +/** + * @author TheElk801 + */ +public enum CommanderCastCountValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability source, Effect effect) { + CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class); + return watcher != null ? watcher.getPlayerCount(source.getControllerId()) : 0; + } + + @Override + public CommanderCastCountValue copy() { + return CommanderCastCountValue.instance; + } + + @Override + public String toString() { + return "for each"; + } + + @Override + public String getMessage() { + return "time you've cast a commander from the command zone this game"; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java b/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java index 7a7e10b7406..31a707aefa8 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CommanderStormAbility.java @@ -42,17 +42,18 @@ public class CommanderStormAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(getSourceId())) { - StackObject spell = game.getStack().getStackObject(getSourceId()); - if (spell instanceof Spell) { - for (Effect effect : this.getEffects()) { - effect.setValue("StormSpell", spell); - effect.setValue("StormSpellRef", new MageObjectReference(spell.getId(), game)); - } - return true; - } + if (!event.getSourceId().equals(getSourceId())) { + return false; } - return false; + StackObject spell = game.getStack().getStackObject(getSourceId()); + if (!(spell instanceof Spell)) { + return false; + } + for (Effect effect : this.getEffects()) { + effect.setValue("StormSpell", spell); + effect.setValue("StormSpellRef", new MageObjectReference(spell.getId(), game)); + } + return true; } @Override @@ -65,11 +66,11 @@ public class CommanderStormAbility extends TriggeredAbilityImpl { class CommanderStormEffect extends OneShotEffect { - public CommanderStormEffect() { + CommanderStormEffect() { super(Outcome.Copy); } - public CommanderStormEffect(final CommanderStormEffect effect) { + private CommanderStormEffect(final CommanderStormEffect effect) { super(effect); } @@ -79,14 +80,19 @@ class CommanderStormEffect extends OneShotEffect { if (spellRef == null) { return false; } - int stormCount = 0; Player player = game.getPlayer(source.getControllerId()); if (player == null) { return false; } - stormCount = game.getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER).stream() - .map((commanderId) -> game.getState().getWatcher(CommanderPlaysCountWatcher.class).getPlaysCount(commanderId)) - .reduce(stormCount, Integer::sum); + CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class); + if (watcher == null) { + return false; + } + int stormCount = game + .getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER) + .stream() + .mapToInt(watcher::getPlaysCount) + .sum(); if (stormCount == 0) { return true; } diff --git a/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java b/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java index e8a093451ab..d96483b2278 100644 --- a/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java @@ -5,9 +5,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.players.Player; import mage.watchers.Watcher; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -21,6 +21,7 @@ import java.util.UUID; public class CommanderPlaysCountWatcher extends Watcher { private final Map playsCount = new HashMap<>(); + private final Map playerCount = new HashMap<>(); public CommanderPlaysCountWatcher() { super(WatcherScope.GAME); @@ -28,27 +29,31 @@ public class CommanderPlaysCountWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() != EventType.LAND_PLAYED && event.getType() != EventType.SPELL_CAST) { + if (event.getType() != EventType.LAND_PLAYED + && event.getType() != EventType.SPELL_CAST) { return; } - - UUID possibleCommanderId = event.getSourceId(); - boolean isCommanderObject = false; - for (Player player : game.getPlayers().values()) { - if (game.getCommandersIds(player).contains(possibleCommanderId)) { - isCommanderObject = true; - break; - } - } - - if (isCommanderObject && event.getZone() == Zone.COMMAND) { - int count = playsCount.getOrDefault(possibleCommanderId, 0); - count++; - playsCount.put(possibleCommanderId, count); + boolean isCommanderObject = game + .getPlayerList() + .stream() + .map(game::getPlayer) + .map(game::getCommandersIds) + .flatMap(Collection::stream) + .anyMatch(event.getSourceId()::equals); + if (!isCommanderObject || event.getZone() != Zone.COMMAND) { + return; } + playsCount.putIfAbsent(event.getSourceId(), 0); + playsCount.computeIfPresent(event.getSourceId(), (u, i) -> i + 1); + playerCount.putIfAbsent(event.getPlayerId(), 0); + playerCount.compute(event.getPlayerId(), (u, i) -> i + 1); } public int getPlaysCount(UUID commanderId) { return this.playsCount.getOrDefault(commanderId, 0); } + + public int getPlayerCount(UUID playerId) { + return this.playerCount.getOrDefault(playerId, 0); + } }