Merge pull request #6038 from ssouders412/master

Implemented K'rrik, Son of Yawgmoth
This commit is contained in:
Oleg Agafonov 2019-11-13 10:15:13 +01:00 committed by GitHub
commit 41dc256147
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 599 additions and 311 deletions

View file

@ -0,0 +1,108 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.LifelinkAbility;
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.SubType;
import mage.constants.SubLayer;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterMana;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author ssouders412
*/
public final class KrrikSonOfYawgmoth extends CardImpl {
private static final FilterSpell filterSpell = new FilterSpell("a black spell");
static {
filterSpell.add(new ColorPredicate(ObjectColor.BLACK));
}
public KrrikSonOfYawgmoth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B/P}{B/P}{B/P}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HORROR);
this.subtype.add(SubType.MINION);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// ({B/P} can be paid with either {B} or 2 life.)
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// For each {B} in a cost, you may pay 2 life rather than pay that mana.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KrrikSonOfYawgmothPhyrexianEffect()));
// Whenever you cast a black spell, put a +1/+1 counter on K'rrik, Son of Yawgmoth.
this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filterSpell, false));
}
private KrrikSonOfYawgmoth(final KrrikSonOfYawgmoth card) {
super(card);
}
@Override
public KrrikSonOfYawgmoth copy() {
return new KrrikSonOfYawgmoth(this);
}
}
class KrrikSonOfYawgmothPhyrexianEffect extends ContinuousEffectImpl {
public KrrikSonOfYawgmothPhyrexianEffect() {
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
this.staticText = "for each {B} in a cost, you may pay 2 life rather than pay that mana";
}
public KrrikSonOfYawgmothPhyrexianEffect(final KrrikSonOfYawgmothPhyrexianEffect effect) {
super(effect);
}
@Override
public KrrikSonOfYawgmothPhyrexianEffect copy() {
return new KrrikSonOfYawgmothPhyrexianEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
FilterMana phyrexianBlack = new FilterMana();
phyrexianBlack.setBlack(true);
if (controller != null && sourcePermanent != null) {
for (UUID playerId: game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null)
{
player.addPhyrexianToColors(phyrexianBlack);
}
}
return true;
}
return false;
}
}

View file

@ -159,6 +159,7 @@ public final class Commander2019Edition extends ExpansionSet {
cards.add(new SetCardInfo("Jace's Sanctum", 88, Rarity.RARE, mage.cards.j.JacesSanctum.class)); cards.add(new SetCardInfo("Jace's Sanctum", 88, Rarity.RARE, mage.cards.j.JacesSanctum.class));
cards.add(new SetCardInfo("Jungle Hollow", 254, Rarity.COMMON, mage.cards.j.JungleHollow.class)); cards.add(new SetCardInfo("Jungle Hollow", 254, Rarity.COMMON, mage.cards.j.JungleHollow.class));
cards.add(new SetCardInfo("Jungle Shrine", 255, Rarity.UNCOMMON, mage.cards.j.JungleShrine.class)); cards.add(new SetCardInfo("Jungle Shrine", 255, Rarity.UNCOMMON, mage.cards.j.JungleShrine.class));
cards.add(new SetCardInfo("K'rrik, Son of Yawgmoth", 18, Rarity.RARE, mage.cards.k.KrrikSonOfYawgmoth.class));
cards.add(new SetCardInfo("Kadena's Silencer", 8, Rarity.RARE, mage.cards.k.KadenasSilencer.class)); cards.add(new SetCardInfo("Kadena's Silencer", 8, Rarity.RARE, mage.cards.k.KadenasSilencer.class));
cards.add(new SetCardInfo("Kadena, Slinking Sorcerer", 45, Rarity.MYTHIC, mage.cards.k.KadenaSlinkingSorcerer.class)); cards.add(new SetCardInfo("Kadena, Slinking Sorcerer", 45, Rarity.MYTHIC, mage.cards.k.KadenaSlinkingSorcerer.class));
cards.add(new SetCardInfo("Kazandu Refuge", 256, Rarity.UNCOMMON, mage.cards.k.KazanduRefuge.class)); cards.add(new SetCardInfo("Kazandu Refuge", 256, Rarity.UNCOMMON, mage.cards.k.KazanduRefuge.class));

View file

@ -59,6 +59,7 @@ import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import mage.filter.FilterMana;
import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*; import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*;
@ -3462,4 +3463,19 @@ public class TestPlayer implements Player {
public void setChooseStrictMode(boolean enable) { public void setChooseStrictMode(boolean enable) {
this.strictChooseMode = enable; this.strictChooseMode = enable;
} }
@Override
public void addPhyrexianToColors(FilterMana colors) {
computerPlayer.addPhyrexianToColors(colors);
}
@Override
public void removePhyrexianFromColors(FilterMana colors) {
computerPlayer.removePhyrexianFromColors(colors);
}
@Override
public FilterMana getPhyrexianColors() {
return computerPlayer.getPhyrexianColors();
}
} }

View file

@ -20,6 +20,7 @@ import mage.counters.Counters;
import mage.designations.Designation; import mage.designations.Designation;
import mage.designations.DesignationType; import mage.designations.DesignationType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterMana;
import mage.game.Game; import mage.game.Game;
import mage.game.Graveyard; import mage.game.Graveyard;
import mage.game.Table; import mage.game.Table;
@ -1371,4 +1372,19 @@ public class PlayerStub implements Player {
return hash; return hash;
} }
@Override
public void addPhyrexianToColors(FilterMana colors) {
}
@Override
public void removePhyrexianFromColors(FilterMana colors) {
}
@Override
public FilterMana getPhyrexianColors() {
return (new FilterMana());
}
} }

View file

@ -17,6 +17,7 @@ import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.SplitCard; import mage.cards.SplitCard;
import mage.constants.*; import mage.constants.*;
import mage.filter.FilterMana;
import mage.game.Game; import mage.game.Game;
import mage.game.command.Emblem; import mage.game.command.Emblem;
import mage.game.command.Plane; import mage.game.command.Plane;
@ -548,6 +549,11 @@ public abstract class AbilityImpl implements Ability {
Iterator<ManaCost> costIterator = manaCostsToPay.iterator(); Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
while (costIterator.hasNext()) { while (costIterator.hasNext()) {
ManaCost cost = costIterator.next(); ManaCost cost = costIterator.next();
PhyrexianManaCost tempPhyrexianCost = null;
Mana mana = cost.getMana();
FilterMana phyrexianColors = controller.getPhyrexianColors();
if (cost instanceof PhyrexianManaCost) { if (cost instanceof PhyrexianManaCost) {
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost; PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost;
PayLifeCost payLifeCost = new PayLifeCost(2); PayLifeCost payLifeCost = new PayLifeCost(2);
@ -557,6 +563,37 @@ public abstract class AbilityImpl implements Ability {
costs.add(payLifeCost); costs.add(payLifeCost);
} }
} }
/* K'rrik, Son of Yawgmoth ability check */
else if (phyrexianColors != null) {
int phyrexianEnabledPips = mana.count(phyrexianColors);
if (phyrexianEnabledPips > 0) {
/* find which color mana is in the cost and set it in the temp Phyrexian cost */
if (phyrexianColors.isWhite() && mana.getWhite() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.W);
}
else if (phyrexianColors.isBlue() && mana.getBlue() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.U);
}
else if (phyrexianColors.isBlack() && mana.getBlack() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.B);
}
else if (phyrexianColors.isRed() && mana.getRed() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.R);
}
else if (phyrexianColors.isGreen() && mana.getGreen() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.G);
}
if (tempPhyrexianCost != null) {
PayLifeCost payLifeCost = new PayLifeCost(2);
if (payLifeCost.canPay(this, sourceId, controller.getId(), game)
&& controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + tempPhyrexianCost.getBaseText() + '?', this, game)) {
costIterator.remove();
costs.add(payLifeCost);
}
}
}
}
} }
} }

View file

@ -12,6 +12,7 @@ import mage.constants.ColoredManaSymbol;
import mage.constants.ManaType; import mage.constants.ManaType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.filter.Filter; import mage.filter.Filter;
import mage.filter.FilterMana;
import mage.game.Game; import mage.game.Game;
import mage.players.ManaPool; import mage.players.ManaPool;
import mage.players.Player; import mage.players.Player;
@ -166,6 +167,11 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
while (manaCostIterator.hasNext()) { while (manaCostIterator.hasNext()) {
ManaCost manaCost = manaCostIterator.next(); ManaCost manaCost = manaCostIterator.next();
PhyrexianManaCost tempPhyrexianCost = null;
Mana mana = manaCost.getMana();
FilterMana phyrexianColors = player.getPhyrexianColors();
if (manaCost instanceof PhyrexianManaCost) { if (manaCost instanceof PhyrexianManaCost) {
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) manaCost; PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) manaCost;
PayLifeCost payLifeCost = new PayLifeCost(2); PayLifeCost payLifeCost = new PayLifeCost(2);
@ -175,6 +181,37 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
tempCosts.add(payLifeCost); tempCosts.add(payLifeCost);
} }
} }
/* K'rrik, Son of Yawgmoth ability check */
else if (phyrexianColors != null) {
int phyrexianEnabledPips = mana.count(phyrexianColors);
if (phyrexianEnabledPips > 0) {
/* find which color mana is in the cost and set it in the temp Phyrexian cost */
if (phyrexianColors.isWhite() && mana.getWhite() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.W);
}
else if (phyrexianColors.isBlue() && mana.getBlue() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.U);
}
else if (phyrexianColors.isBlack() && mana.getBlack() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.B);
}
else if (phyrexianColors.isRed() && mana.getRed() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.R);
}
else if (phyrexianColors.isGreen() && mana.getGreen() > 0) {
tempPhyrexianCost = new PhyrexianManaCost(ColoredManaSymbol.G);
}
if (tempPhyrexianCost != null) {
PayLifeCost payLifeCost = new PayLifeCost(2);
if (payLifeCost.canPay(source, source.getSourceId(), player.getId(), game)
&& player.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + tempPhyrexianCost.getBaseText() + '?', source, game)) {
manaCostIterator.remove();
tempCosts.add(payLifeCost);
}
}
}
}
} }
tempCosts.pay(source, game, source.getSourceId(), player.getId(), false, null); tempCosts.pay(source, game, source.getSourceId(), player.getId(), false, null);

View file

@ -21,6 +21,7 @@ import mage.counters.Counters;
import mage.designations.Designation; import mage.designations.Designation;
import mage.designations.DesignationType; import mage.designations.DesignationType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterMana;
import mage.game.Game; import mage.game.Game;
import mage.game.Graveyard; import mage.game.Graveyard;
import mage.game.Table; import mage.game.Table;
@ -894,4 +895,9 @@ public interface Player extends MageItem, Copyable<Player> {
List<Designation> getDesignations(); List<Designation> getDesignations();
void addPhyrexianToColors(FilterMana colors);
void removePhyrexianFromColors(FilterMana colors);
FilterMana getPhyrexianColors();
} }

View file

@ -36,6 +36,7 @@ import mage.designations.Designation;
import mage.designations.DesignationType; import mage.designations.DesignationType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterMana;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreatureForCombat; import mage.filter.common.FilterCreatureForCombat;
import mage.filter.common.FilterCreatureForCombatBlock; import mage.filter.common.FilterCreatureForCombatBlock;
@ -174,6 +175,8 @@ public abstract class PlayerImpl implements Player, Serializable {
protected List<Designation> designations = new ArrayList<>(); protected List<Designation> designations = new ArrayList<>();
protected FilterMana phyrexianColors;
/** /**
* During some steps we can't play anything * During some steps we can't play anything
*/ */
@ -191,6 +194,7 @@ public abstract class PlayerImpl implements Player, Serializable {
manaPool = new ManaPool(playerId); manaPool = new ManaPool(playerId);
library = new Library(playerId); library = new Library(playerId);
sideboard = new CardsImpl(); sideboard = new CardsImpl();
phyrexianColors = new FilterMana();
} }
protected PlayerImpl(UUID id) { protected PlayerImpl(UUID id) {
@ -274,6 +278,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdManaCosts = player.castSourceIdManaCosts; this.castSourceIdManaCosts = player.castSourceIdManaCosts;
this.castSourceIdCosts = player.castSourceIdCosts; this.castSourceIdCosts = player.castSourceIdCosts;
this.payManaMode = player.payManaMode; this.payManaMode = player.payManaMode;
this.phyrexianColors = player.phyrexianColors.copy();
this.designations.addAll(player.designations); this.designations.addAll(player.designations);
} }
@ -340,6 +345,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana(); this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana();
this.castSourceIdManaCosts = player.getCastSourceIdManaCosts(); this.castSourceIdManaCosts = player.getCastSourceIdManaCosts();
this.castSourceIdCosts = player.getCastSourceIdCosts(); this.castSourceIdCosts = player.getCastSourceIdCosts();
this.phyrexianColors = player.getPhyrexianColors().copy();
this.designations.clear(); this.designations.clear();
this.designations.addAll(player.getDesignations()); this.designations.addAll(player.getDesignations());
@ -417,6 +423,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdManaCosts = null; this.castSourceIdManaCosts = null;
this.castSourceIdCosts = null; this.castSourceIdCosts = null;
this.getManaPool().init(); // needed to remove mana that not empties on step change from previous game if left this.getManaPool().init(); // needed to remove mana that not empties on step change from previous game if left
this.phyrexianColors = new FilterMana();
this.designations.clear(); this.designations.clear();
} }
@ -443,6 +450,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdManaCosts = null; this.castSourceIdManaCosts = null;
this.castSourceIdCosts = null; this.castSourceIdCosts = null;
this.getManaPool().clearEmptyManaPoolRules(); this.getManaPool().clearEmptyManaPoolRules();
this.phyrexianColors = new FilterMana();
} }
@Override @Override
@ -4160,4 +4168,48 @@ public abstract class PlayerImpl implements Player, Serializable {
hash = 89 * hash + Objects.hashCode(this.playerId); hash = 89 * hash + Objects.hashCode(this.playerId);
return hash; return hash;
} }
@Override
public void addPhyrexianToColors(FilterMana colors) {
if (colors.isWhite()) {
this.phyrexianColors.setWhite(true);
}
if (colors.isBlue()) {
this.phyrexianColors.setBlue(true);
}
if (colors.isBlack()) {
this.phyrexianColors.setBlack(true);
}
if (colors.isRed()) {
this.phyrexianColors.setRed(true);
}
if (colors.isGreen()) {
this.phyrexianColors.setGreen(true);
}
}
@Override
public void removePhyrexianFromColors(FilterMana colors) {
if (colors.isWhite()) {
this.phyrexianColors.setWhite(false);
}
if (colors.isBlue()) {
this.phyrexianColors.setBlue(false);
}
if (colors.isBlack()) {
this.phyrexianColors.setBlack(false);
}
if (colors.isRed()) {
this.phyrexianColors.setRed(false);
}
if (colors.isGreen()) {
this.phyrexianColors.setGreen(false);
}
}
@Override
public FilterMana getPhyrexianColors() {
return this.phyrexianColors;
}
} }

View file

@ -31,6 +31,7 @@ import java.util.UUID;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import mage.filter.FilterMana;
public class StubPlayer extends PlayerImpl implements Player { public class StubPlayer extends PlayerImpl implements Player {
@ -218,4 +219,18 @@ public class StubPlayer extends PlayerImpl implements Player {
} }
@Override
public void addPhyrexianToColors(FilterMana colors) {
}
@Override
public void removePhyrexianFromColors(FilterMana colors) {
}
@Override
public FilterMana getPhyrexianColors() {
return (new FilterMana());
}
} }