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("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("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, Slinking Sorcerer", 45, Rarity.MYTHIC, mage.cards.k.KadenaSlinkingSorcerer.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.Pattern;
import java.util.stream.Collectors;
import mage.filter.FilterMana;
import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*;
@ -3462,4 +3463,19 @@ public class TestPlayer implements Player {
public void setChooseStrictMode(boolean 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.DesignationType;
import mage.filter.FilterPermanent;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.game.Graveyard;
import mage.game.Table;
@ -1371,4 +1372,19 @@ public class PlayerStub implements Player {
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.SplitCard;
import mage.constants.*;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.game.command.Emblem;
import mage.game.command.Plane;
@ -548,6 +549,11 @@ public abstract class AbilityImpl implements Ability {
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
while (costIterator.hasNext()) {
ManaCost cost = costIterator.next();
PhyrexianManaCost tempPhyrexianCost = null;
Mana mana = cost.getMana();
FilterMana phyrexianColors = controller.getPhyrexianColors();
if (cost instanceof PhyrexianManaCost) {
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost;
PayLifeCost payLifeCost = new PayLifeCost(2);
@ -557,6 +563,37 @@ public abstract class AbilityImpl implements Ability {
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.Outcome;
import mage.filter.Filter;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.players.ManaPool;
import mage.players.Player;
@ -166,6 +167,11 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
while (manaCostIterator.hasNext()) {
ManaCost manaCost = manaCostIterator.next();
PhyrexianManaCost tempPhyrexianCost = null;
Mana mana = manaCost.getMana();
FilterMana phyrexianColors = player.getPhyrexianColors();
if (manaCost instanceof PhyrexianManaCost) {
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) manaCost;
PayLifeCost payLifeCost = new PayLifeCost(2);
@ -175,6 +181,37 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
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);

View file

@ -21,6 +21,7 @@ import mage.counters.Counters;
import mage.designations.Designation;
import mage.designations.DesignationType;
import mage.filter.FilterPermanent;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.game.Graveyard;
import mage.game.Table;
@ -894,4 +895,9 @@ public interface Player extends MageItem, Copyable<Player> {
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.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.FilterMana;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreatureForCombat;
import mage.filter.common.FilterCreatureForCombatBlock;
@ -174,6 +175,8 @@ public abstract class PlayerImpl implements Player, Serializable {
protected List<Designation> designations = new ArrayList<>();
protected FilterMana phyrexianColors;
/**
* During some steps we can't play anything
*/
@ -191,6 +194,7 @@ public abstract class PlayerImpl implements Player, Serializable {
manaPool = new ManaPool(playerId);
library = new Library(playerId);
sideboard = new CardsImpl();
phyrexianColors = new FilterMana();
}
protected PlayerImpl(UUID id) {
@ -274,6 +278,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdManaCosts = player.castSourceIdManaCosts;
this.castSourceIdCosts = player.castSourceIdCosts;
this.payManaMode = player.payManaMode;
this.phyrexianColors = player.phyrexianColors.copy();
this.designations.addAll(player.designations);
}
@ -340,6 +345,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana();
this.castSourceIdManaCosts = player.getCastSourceIdManaCosts();
this.castSourceIdCosts = player.getCastSourceIdCosts();
this.phyrexianColors = player.getPhyrexianColors().copy();
this.designations.clear();
this.designations.addAll(player.getDesignations());
@ -417,6 +423,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdManaCosts = null;
this.castSourceIdCosts = null;
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();
}
@ -443,6 +450,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.castSourceIdManaCosts = null;
this.castSourceIdCosts = null;
this.getManaPool().clearEmptyManaPoolRules();
this.phyrexianColors = new FilterMana();
}
@Override
@ -4160,4 +4168,48 @@ public abstract class PlayerImpl implements Player, Serializable {
hash = 89 * hash + Objects.hashCode(this.playerId);
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 java.util.stream.Collectors.toList;
import mage.filter.FilterMana;
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());
}
}