mirror of
https://github.com/correl/mage.git
synced 2024-11-25 11:09:53 +00:00
[MH2] Implemented Carth the Lion (#7848)
* [MH2] Implemented Carth the Lion * [MH2] Carth the Lion - Fixed loyalty cost modification * Fix copy constructor and add getters/setters * Call sourceObject.adjustCosts before checking cost modifications * Add unit test * Added additional comments, checks and tests; Co-authored-by: Oleg Agafonov <jaydi85@gmail.com>
This commit is contained in:
parent
3ea08e1e7b
commit
29d3f96340
7 changed files with 353 additions and 24 deletions
130
Mage.Sets/src/mage/cards/c/CarthTheLion.java
Normal file
130
Mage.Sets/src/mage/cards/c/CarthTheLion.java
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.LoyaltyAbility;
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
|
||||||
|
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.filter.common.FilterPlaneswalkerCard;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author weirddan455
|
||||||
|
*/
|
||||||
|
public final class CarthTheLion extends CardImpl {
|
||||||
|
|
||||||
|
public CarthTheLion(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}");
|
||||||
|
|
||||||
|
this.addSuperType(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.WARRIOR);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
|
// Whenever Carth the Lion enters the battlefield, or a planeswalker you control dies, look at the top seven cards of your library.
|
||||||
|
// You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
||||||
|
this.addAbility(new CarthTheLionTriggeredAbility());
|
||||||
|
|
||||||
|
// Planeswalkers' loyalty abilities you activate cost an additonal {+1} to activate.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new CarthTheLionLoyaltyCostEffect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CarthTheLion(final CarthTheLion card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarthTheLion copy() {
|
||||||
|
return new CarthTheLion(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CarthTheLionTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
private static final FilterPlaneswalkerCard filter = new FilterPlaneswalkerCard("a planeswalker card");
|
||||||
|
|
||||||
|
public CarthTheLionTriggeredAbility() {
|
||||||
|
super(Zone.BATTLEFIELD, new LookLibraryAndPickControllerEffect(
|
||||||
|
7, 1, filter, true, false, Zone.HAND, true)
|
||||||
|
.setBackInRandomOrder(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CarthTheLionTriggeredAbility(final CarthTheLionTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarthTheLionTriggeredAbility copy() {
|
||||||
|
return new CarthTheLionTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
|
||||||
|
|| event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
|
||||||
|
&& event.getTargetId().equals(getSourceId())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getPlayerId().equals(getControllerId())) {
|
||||||
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
|
if (zEvent.isDiesEvent()) {
|
||||||
|
Permanent permanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId());
|
||||||
|
return permanent != null && permanent.isPlaneswalker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Whenever {this} enters the battlefield, or a planeswalker you control dies, " + super.getRule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CarthTheLionLoyaltyCostEffect extends CostModificationEffectImpl {
|
||||||
|
|
||||||
|
public CarthTheLionLoyaltyCostEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
|
||||||
|
this.staticText = "Planeswalkers' loyalty abilities you activate cost an additonal +1 to activate";
|
||||||
|
}
|
||||||
|
|
||||||
|
private CarthTheLionLoyaltyCostEffect(final CarthTheLionLoyaltyCostEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarthTheLionLoyaltyCostEffect copy() {
|
||||||
|
return new CarthTheLionLoyaltyCostEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||||
|
if (abilityToModify instanceof LoyaltyAbility) {
|
||||||
|
((LoyaltyAbility) abilityToModify).increaseLoyaltyCost(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
|
return abilityToModify instanceof LoyaltyAbility && abilityToModify.getControllerId().equals(source.getControllerId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,6 +72,7 @@ public final class ModernHorizons2 extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Burdened Aerialist", 38, Rarity.COMMON, mage.cards.b.BurdenedAerialist.class));
|
cards.add(new SetCardInfo("Burdened Aerialist", 38, Rarity.COMMON, mage.cards.b.BurdenedAerialist.class));
|
||||||
cards.add(new SetCardInfo("Cabal Coffers", 301, Rarity.MYTHIC, mage.cards.c.CabalCoffers.class));
|
cards.add(new SetCardInfo("Cabal Coffers", 301, Rarity.MYTHIC, mage.cards.c.CabalCoffers.class));
|
||||||
cards.add(new SetCardInfo("Cabal Initiate", 78, Rarity.COMMON, mage.cards.c.CabalInitiate.class));
|
cards.add(new SetCardInfo("Cabal Initiate", 78, Rarity.COMMON, mage.cards.c.CabalInitiate.class));
|
||||||
|
cards.add(new SetCardInfo("Carth the Lion", 189, Rarity.RARE, mage.cards.c.CarthTheLion.class));
|
||||||
cards.add(new SetCardInfo("Calibrated Blast", 118, Rarity.RARE, mage.cards.c.CalibratedBlast.class));
|
cards.add(new SetCardInfo("Calibrated Blast", 118, Rarity.RARE, mage.cards.c.CalibratedBlast.class));
|
||||||
cards.add(new SetCardInfo("Caprichrome", 9, Rarity.UNCOMMON, mage.cards.c.Caprichrome.class));
|
cards.add(new SetCardInfo("Caprichrome", 9, Rarity.UNCOMMON, mage.cards.c.Caprichrome.class));
|
||||||
cards.add(new SetCardInfo("Captain Ripley Vance", 119, Rarity.UNCOMMON, mage.cards.c.CaptainRipleyVance.class));
|
cards.add(new SetCardInfo("Captain Ripley Vance", 119, Rarity.UNCOMMON, mage.cards.c.CaptainRipleyVance.class));
|
||||||
|
|
|
@ -154,7 +154,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void testCounteredBecauseOfNoLegalTarget() {
|
public void testCounteredBecauseOfNoLegalTarget() {
|
||||||
// TODO: rewrite test, it's wrong and misleading-- user report about Griselbrand was destroyed by Terminate after splice anounce, but tests don't use it at all (Griselbrand legal target all the time)
|
// TODO: rewrite test, it's wrong and misleading-- user report about Griselbrand was destroyed by Terminate after splice announce, but tests don't use it at all (Griselbrand legal target all the time)
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package org.mage.test.cards.cost.modification;
|
package org.mage.test.cards.cost.modification;
|
||||||
|
|
||||||
|
import mage.abilities.LoyaltyAbility;
|
||||||
|
import mage.abilities.costs.common.PayVariableLoyaltyCost;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
@ -382,4 +386,100 @@ public class CostModificationTest extends CardTestPlayerBase {
|
||||||
execute();
|
execute();
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PlaneswalkerLoyalty_CostModification_Single() {
|
||||||
|
// Carth the Lion
|
||||||
|
// Planeswalkers' loyalty abilities you activate cost an additional {+1} to activate.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Carth the Lion", 1);
|
||||||
|
//
|
||||||
|
// Vivien Reid
|
||||||
|
// 5 Loyalty
|
||||||
|
// +1, -3, -8 Abilities
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Vivien Reid", 1);
|
||||||
|
//
|
||||||
|
// Huatli, Warrior Poet
|
||||||
|
// 3 Loyalty
|
||||||
|
// Testing X Ability
|
||||||
|
// −X: Huatli, Warrior Poet deals X damage divided as you choose among any number of target creatures. Creatures dealt damage this way can’t block this turn.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Huatli, Warrior Poet", 1);
|
||||||
|
//
|
||||||
|
// 2 toughness creatures for Huatli to kill
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Ghitu Lavarunner", 1);
|
||||||
|
|
||||||
|
// Vivien: make cost +2 instead +1 (total 7 counters)
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Look at the top four");
|
||||||
|
setChoice(playerA, "No");
|
||||||
|
checkPermanentCounters("Vivien Reid counter check", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Vivien Reid", CounterType.LOYALTY, 7);
|
||||||
|
|
||||||
|
// loyalty cost modification doesn't affect card rule's text, so it still shown an old cost value for a user
|
||||||
|
|
||||||
|
// Vivien: make cost -7 instead -8
|
||||||
|
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "-8: You get an emblem");
|
||||||
|
|
||||||
|
// Huatli: check x cost changes
|
||||||
|
runCode("check x cost", 3, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||||
|
Permanent huatli = game.getBattlefield().getAllActivePermanents().stream().filter(p -> p.getName().equals("Huatli, Warrior Poet")).findFirst().orElse(null);
|
||||||
|
Assert.assertNotNull("must have huatli on battlefield", huatli);
|
||||||
|
LoyaltyAbility ability = (LoyaltyAbility) huatli.getAbilities(game).stream().filter(a -> a.getRule().startsWith("-X: ")).findFirst().orElse(null);
|
||||||
|
Assert.assertNotNull("must have loyalty ability", ability);
|
||||||
|
// counters: 3
|
||||||
|
// cost modification: +1
|
||||||
|
// max possible X to pay: 3 + 1 = 4
|
||||||
|
PayVariableLoyaltyCost cost = (PayVariableLoyaltyCost) ability.getCosts().get(0);
|
||||||
|
Assert.assertEquals("must have max possible X as 4", 4, cost.getMaxValue(ability, game));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Huatli: make x cost -3 instead -4
|
||||||
|
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "-X: {this} deals X damage divided as you choose");
|
||||||
|
setChoice(playerA, "X=4");
|
||||||
|
addTargetAmount(playerA, "Grizzly Bears", 2);
|
||||||
|
addTargetAmount(playerA, "Ghitu Lavarunner", 2);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(3, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Vivien Reid", 1);
|
||||||
|
assertGraveyardCount(playerA, "Huatli, Warrior Poet", 1);
|
||||||
|
assertGraveyardCount(playerB, "Grizzly Bears", 1);
|
||||||
|
assertGraveyardCount(playerB, "Ghitu Lavarunner", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PlaneswalkerLoyalty_CostModification_Multiple() {
|
||||||
|
// Carth the Lion
|
||||||
|
// Planeswalkers' loyalty abilities you activate cost an additional {+1} to activate.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Carth the Lion", 1);
|
||||||
|
//
|
||||||
|
// Vivien Reid
|
||||||
|
// 5 Loyalty
|
||||||
|
// +1, -3, -8 Abilities
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Vivien Reid", 1);
|
||||||
|
//
|
||||||
|
// You may have Spark Double enter the battlefield as a copy of a creature or planeswalker you control...
|
||||||
|
addCard(Zone.HAND, playerA, "Spark Double", 2); // {3}{U}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 2 * 4);
|
||||||
|
|
||||||
|
checkPlayableAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "-8:", false);
|
||||||
|
|
||||||
|
// prepare duplicates
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spark Double");
|
||||||
|
setChoice(playerA, "Yes"); // copy
|
||||||
|
setChoice(playerA, "Carth the Lion"); // copy target
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spark Double");
|
||||||
|
setChoice(playerA, "Yes"); // copy
|
||||||
|
setChoice(playerA, "Carth the Lion"); // copy target
|
||||||
|
|
||||||
|
// x3 lions gives +3 in cost reduction (-8 -> -5)
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
checkPlayableAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "-8:", true);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
package mage.abilities;
|
package mage.abilities;
|
||||||
|
|
||||||
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.common.PayLoyaltyCost;
|
import mage.abilities.costs.common.PayLoyaltyCost;
|
||||||
import mage.abilities.costs.common.PayVariableLoyaltyCost;
|
import mage.abilities.costs.common.PayVariableLoyaltyCost;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
|
@ -9,7 +9,6 @@ import mage.constants.TimingRule;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class LoyaltyAbility extends ActivatedAbilityImpl {
|
public class LoyaltyAbility extends ActivatedAbilityImpl {
|
||||||
|
@ -43,4 +42,49 @@ public class LoyaltyAbility extends ActivatedAbilityImpl {
|
||||||
return new LoyaltyAbility(this);
|
return new LoyaltyAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change loyalty cost by amount value
|
||||||
|
*
|
||||||
|
* @param amount
|
||||||
|
*/
|
||||||
|
public void increaseLoyaltyCost(int amount) {
|
||||||
|
|
||||||
|
// loyalty cost modification rules from Carth the Lion
|
||||||
|
|
||||||
|
// If a planeswalker’s loyalty ability normally has a cost of [+1], Carth’s ability makes it cost [+2] instead.
|
||||||
|
// A cost of [0] would become [+1], and a cost of [-6] would become [-5].
|
||||||
|
// (2021-06-18)
|
||||||
|
//
|
||||||
|
// If you somehow manage to control two Carths (perhaps because of Spark Double), the cost-changing effect is
|
||||||
|
// cumulative. In total, loyalty abilities will cost an additional [+2] to activate.
|
||||||
|
// (2021-06-18)
|
||||||
|
//
|
||||||
|
// The total cost of a planeswalker’s loyalty ability is calculated before any counters are added or removed.
|
||||||
|
// If a loyalty ability normally costs [-3] to activate, you do not remove three counters from it and then
|
||||||
|
// put one counter on it. You remove two counters at one time when you pay the cost.
|
||||||
|
// (2021-06-18)
|
||||||
|
//
|
||||||
|
// If an effect replaces the number of counters that would be placed on a planeswalker, such as that of
|
||||||
|
// Vorinclex, Monstrous Raider, that replacement happens only once, at the time payment is made.
|
||||||
|
// (2021-06-18)
|
||||||
|
|
||||||
|
// cost modification support only 1 cost item
|
||||||
|
int staticCount = 0;
|
||||||
|
for (Cost cost : costs) {
|
||||||
|
if (cost instanceof PayLoyaltyCost) {
|
||||||
|
// static cost
|
||||||
|
PayLoyaltyCost staticCost = (PayLoyaltyCost) cost;
|
||||||
|
staticCost.setAmount(staticCost.getAmount() + amount);
|
||||||
|
staticCount++;
|
||||||
|
} else if (cost instanceof PayVariableLoyaltyCost) {
|
||||||
|
// x cost (after x announce: x cost + static cost)
|
||||||
|
PayVariableLoyaltyCost xCost = (PayVariableLoyaltyCost) cost;
|
||||||
|
xCost.setCostModification(xCost.getCostModification() + amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (staticCount > 1) {
|
||||||
|
throw new IllegalArgumentException(String.format("Loyalty ability must have only 1 static cost, but has %d: %s",
|
||||||
|
staticCount, this.getRule()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.LoyaltyAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.CostImpl;
|
import mage.abilities.costs.CostImpl;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
|
@ -11,19 +11,14 @@ import mage.game.permanent.Permanent;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class PayLoyaltyCost extends CostImpl {
|
public class PayLoyaltyCost extends CostImpl {
|
||||||
|
|
||||||
private final int amount;
|
private int amount;
|
||||||
|
|
||||||
public PayLoyaltyCost(int amount) {
|
public PayLoyaltyCost(int amount) {
|
||||||
this.amount = amount;
|
setAmount(amount);
|
||||||
this.text = Integer.toString(amount);
|
|
||||||
if (amount > 0) {
|
|
||||||
this.text = '+' + this.text;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PayLoyaltyCost(PayLoyaltyCost cost) {
|
public PayLoyaltyCost(PayLoyaltyCost cost) {
|
||||||
|
@ -34,7 +29,26 @@ public class PayLoyaltyCost extends CostImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||||
Permanent planeswalker = game.getPermanent(source.getSourceId());
|
Permanent planeswalker = game.getPermanent(source.getSourceId());
|
||||||
return planeswalker != null && planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + amount >= 0 && planeswalker.canLoyaltyBeUsed(game);
|
if (planeswalker == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int loyaltyCost = amount;
|
||||||
|
|
||||||
|
// apply cost modification
|
||||||
|
if (ability instanceof LoyaltyAbility) {
|
||||||
|
LoyaltyAbility copiedAbility = ((LoyaltyAbility) ability).copy();
|
||||||
|
planeswalker.adjustCosts(copiedAbility, game);
|
||||||
|
game.getContinuousEffects().costModification(copiedAbility, game);
|
||||||
|
loyaltyCost = 0;
|
||||||
|
for (Cost cost : copiedAbility.getCosts()) {
|
||||||
|
if (cost instanceof PayLoyaltyCost) {
|
||||||
|
loyaltyCost += ((PayLoyaltyCost) cost).getAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + loyaltyCost >= 0 && planeswalker.canLoyaltyBeUsed(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +57,6 @@ public class PayLoyaltyCost extends CostImpl {
|
||||||
* ability whose cost has you put loyalty counters on a planeswalker, the
|
* ability whose cost has you put loyalty counters on a planeswalker, the
|
||||||
* number you put on isn't doubled. This is because those counters are put
|
* number you put on isn't doubled. This is because those counters are put
|
||||||
* on as a cost, not as an effect.
|
* on as a cost, not as an effect.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||||
|
@ -65,4 +78,16 @@ public class PayLoyaltyCost extends CostImpl {
|
||||||
return new PayLoyaltyCost(this);
|
return new PayLoyaltyCost(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(int amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
|
||||||
|
this.text = Integer.toString(this.amount);
|
||||||
|
if (this.amount > 0) {
|
||||||
|
this.text = '+' + this.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.LoyaltyAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class PayVariableLoyaltyCost extends VariableCostImpl {
|
public class PayVariableLoyaltyCost extends VariableCostImpl {
|
||||||
|
|
||||||
|
// dynamic x cost modification from effects like Carth the Lion
|
||||||
|
// GUI only (applies to -X value on X announce)
|
||||||
|
// Example:
|
||||||
|
// - counters: 3
|
||||||
|
// - cost modification: +1
|
||||||
|
// - max possible X to pay: 4
|
||||||
|
private int costModification = 0;
|
||||||
|
|
||||||
public PayVariableLoyaltyCost() {
|
public PayVariableLoyaltyCost() {
|
||||||
super("loyality counters to remove");
|
super("loyality counters to remove");
|
||||||
this.text = "-X";
|
this.text = "-X";
|
||||||
|
@ -23,6 +30,7 @@ public class PayVariableLoyaltyCost extends VariableCostImpl {
|
||||||
|
|
||||||
public PayVariableLoyaltyCost(final PayVariableLoyaltyCost cost) {
|
public PayVariableLoyaltyCost(final PayVariableLoyaltyCost cost) {
|
||||||
super(cost);
|
super(cost);
|
||||||
|
this.costModification = cost.costModification;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,7 +41,7 @@ public class PayVariableLoyaltyCost extends VariableCostImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||||
Permanent planeswalker = game.getPermanent(source.getSourceId());
|
Permanent planeswalker = game.getPermanent(source.getSourceId());
|
||||||
return planeswalker!= null && planeswalker.canLoyaltyBeUsed(game);
|
return planeswalker != null && planeswalker.canLoyaltyBeUsed(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,12 +51,33 @@ public class PayVariableLoyaltyCost extends VariableCostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxValue(Ability source, Game game) {
|
public int getMaxValue(Ability source, Game game) {
|
||||||
int maxValue = 0;
|
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||||
if (permanent != null) {
|
if (permanent == null) {
|
||||||
maxValue = permanent.getCounters(game).getCount(CounterType.LOYALTY.getName());
|
return 0;
|
||||||
}
|
|
||||||
return maxValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maxValue = permanent.getCounters(game).getCount(CounterType.LOYALTY.getName());
|
||||||
|
|
||||||
|
// apply cost modification
|
||||||
|
if (source instanceof LoyaltyAbility) {
|
||||||
|
LoyaltyAbility copiedAbility = ((LoyaltyAbility) source).copy();
|
||||||
|
permanent.adjustCosts(copiedAbility, game);
|
||||||
|
game.getContinuousEffects().costModification(copiedAbility, game);
|
||||||
|
for (Cost cost : copiedAbility.getCosts()) {
|
||||||
|
if (cost instanceof PayVariableLoyaltyCost) {
|
||||||
|
maxValue += ((PayVariableLoyaltyCost) cost).getCostModification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCostModification() {
|
||||||
|
return costModification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCostModification(int costModification) {
|
||||||
|
this.costModification = costModification;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue