mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
[ECL] Implement Blossombind, rework how adding counters as a cost works (#14256)
* add attribute for disabling counter adding, refactor cards which use it * modify counter adding costs to check for ability to add counters, fix #13583 * [ECL] Implement Blossombind * rework implementation * remove unnecessary calls to game.processAction() * fix error * fix saga error * update preexisting tests, add new one * apply requested changes
This commit is contained in:
parent
5b4a1618f9
commit
5931ce9179
21 changed files with 401 additions and 253 deletions
|
|
@ -2,21 +2,15 @@ package mage.cards.b;
|
|||
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.common.ruleModifying.CantHaveCountersAllEffect;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -36,7 +30,9 @@ public final class Blightbeetle extends CardImpl {
|
|||
this.addAbility(ProtectionAbility.from(ObjectColor.GREEN));
|
||||
|
||||
// Creatures your opponents control can't have +1/+1 counters put on them.
|
||||
this.addAbility(new SimpleStaticAbility(new BlightbeetleEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(new CantHaveCountersAllEffect(
|
||||
StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURES, CounterType.P1P1
|
||||
)));
|
||||
}
|
||||
|
||||
private Blightbeetle(final Blightbeetle card) {
|
||||
|
|
@ -48,41 +44,3 @@ public final class Blightbeetle extends CardImpl {
|
|||
return new Blightbeetle(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BlightbeetleEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
BlightbeetleEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
staticText = "Creatures your opponents control can't have +1/+1 counters put on them";
|
||||
}
|
||||
|
||||
private BlightbeetleEffect(final BlightbeetleEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlightbeetleEffect copy() {
|
||||
return new BlightbeetleEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!event.getData().equals(CounterType.P1P1.getName())) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanentEntering(event.getTargetId());
|
||||
if (permanent == null) {
|
||||
permanent = game.getPermanent(event.getTargetId());
|
||||
}
|
||||
if (permanent == null || !permanent.isCreature(game)) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(permanent.getControllerId());
|
||||
return player != null && player.hasOpponent(source.getControllerId(), game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
122
Mage.Sets/src/mage/cards/b/Blossombind.java
Normal file
122
Mage.Sets/src/mage/cards/b/Blossombind.java
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.TapEnchantedEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Blossombind extends CardImpl {
|
||||
|
||||
public Blossombind(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
|
||||
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// When this Aura enters, tap enchanted creature.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()));
|
||||
|
||||
// Enchanted creature can't become untapped and can't have counters put on it.
|
||||
Ability ability = new SimpleStaticAbility(new BlossombindUntapEffect());
|
||||
ability.addEffect(new BlossombindCounterEffect());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private Blossombind(final Blossombind card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Blossombind copy() {
|
||||
return new Blossombind(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BlossombindUntapEffect extends ReplacementEffectImpl {
|
||||
|
||||
BlossombindUntapEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Tap);
|
||||
staticText = "enchanted creature can't become untapped";
|
||||
}
|
||||
|
||||
private BlossombindUntapEffect(final BlossombindUntapEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlossombindUntapEffect copy() {
|
||||
return new BlossombindUntapEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return game.getPermanent(event.getTargetId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.UNTAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return source.getSourceId().equals(event.getTargetId());
|
||||
}
|
||||
}
|
||||
|
||||
class BlossombindCounterEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
BlossombindCounterEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
staticText = "and can't have counters put on it";
|
||||
}
|
||||
|
||||
private BlossombindCounterEffect(final BlossombindCounterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlossombindCounterEffect copy() {
|
||||
return new BlossombindCounterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAN_ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return Optional
|
||||
.ofNullable(source.getSourcePermanentIfItStillExists(game))
|
||||
.map(Permanent::getAttachedTo)
|
||||
.filter(event.getTargetId()::equals)
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
|
|
@ -5,11 +5,13 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.ruleModifying.CantHaveCountersAllEffect;
|
||||
import mage.abilities.keyword.InfectAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
|
@ -36,7 +38,9 @@ public final class MeliraSylvokOutcast extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(new MeliraSylvokOutcastEffect()));
|
||||
|
||||
// Creatures you control can't have -1/-1 counters put on them.
|
||||
this.addAbility(new SimpleStaticAbility(new MeliraSylvokOutcastEffect2()));
|
||||
this.addAbility(new SimpleStaticAbility(new CantHaveCountersAllEffect(
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURES, CounterType.M1M1
|
||||
)));
|
||||
|
||||
// Creatures your opponents control lose infect.
|
||||
this.addAbility(new SimpleStaticAbility(new MeliraSylvokOutcastEffect3()));
|
||||
|
|
@ -86,45 +90,6 @@ class MeliraSylvokOutcastEffect extends ReplacementEffectImpl {
|
|||
|
||||
}
|
||||
|
||||
class MeliraSylvokOutcastEffect2 extends ReplacementEffectImpl {
|
||||
|
||||
public MeliraSylvokOutcastEffect2() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.PreventDamage);
|
||||
staticText = "Creatures you control can't have -1/-1 counters put on them";
|
||||
}
|
||||
|
||||
private MeliraSylvokOutcastEffect2(final MeliraSylvokOutcastEffect2 effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeliraSylvokOutcastEffect2 copy() {
|
||||
return new MeliraSylvokOutcastEffect2(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getData().equals(CounterType.M1M1.getName())) {
|
||||
Permanent perm = game.getPermanent(event.getTargetId());
|
||||
if (perm == null) {
|
||||
perm = game.getPermanentEntering(event.getTargetId());
|
||||
}
|
||||
return perm != null && perm.isCreature(game) && perm.isControlledBy(source.getControllerId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class MeliraSylvokOutcastEffect3 extends ContinuousEffectImpl {
|
||||
|
||||
private static FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ruleModifying.CantHaveCountersSourceEffect;
|
||||
|
|
@ -9,16 +7,16 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public final class MelirasKeepers extends CardImpl {
|
||||
|
||||
public MelirasKeepers(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,18 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.ruleModifying.CantHaveCountersAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -25,6 +22,17 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class Solemnity extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent();
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate(),
|
||||
CardType.ENCHANTMENT.getPredicate(),
|
||||
CardType.LAND.getPredicate()
|
||||
));
|
||||
}
|
||||
|
||||
public Solemnity(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
||||
|
||||
|
|
@ -32,7 +40,8 @@ public final class Solemnity extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(new SolemnityEffect()));
|
||||
|
||||
// Counters can't be put on artifacts, creatures, enchantments, or lands.
|
||||
this.addAbility(new SimpleStaticAbility(new SolemnityEffect2()));
|
||||
this.addAbility(new SimpleStaticAbility(new CantHaveCountersAllEffect(filter, null)
|
||||
.setText("counters can't be put on artifacts, creatures, enchantments, or lands")));
|
||||
}
|
||||
|
||||
private Solemnity(final Solemnity card) {
|
||||
|
|
@ -77,57 +86,3 @@ class SolemnityEffect extends ReplacementEffectImpl {
|
|||
return player != null;
|
||||
}
|
||||
}
|
||||
|
||||
class SolemnityEffect2 extends ReplacementEffectImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent();
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate(),
|
||||
CardType.ENCHANTMENT.getPredicate(),
|
||||
CardType.LAND.getPredicate()));
|
||||
}
|
||||
|
||||
public SolemnityEffect2() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "Counters can't be put on artifacts, creatures, enchantments, or lands";
|
||||
}
|
||||
|
||||
private SolemnityEffect2(final SolemnityEffect2 effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SolemnityEffect2 copy() {
|
||||
return new SolemnityEffect2(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
MageObject object = game.getObject(event.getTargetId());
|
||||
Permanent permanent1 = game.getPermanentEntering(event.getTargetId());
|
||||
Permanent permanent2 = game.getPermanent(event.getTargetId());
|
||||
|
||||
if (object instanceof Permanent) {
|
||||
return filter.match((Permanent) object, game);
|
||||
} else if (permanent1 != null) {
|
||||
return filter.match(permanent1, game);
|
||||
} else if (permanent2 != null) {
|
||||
return filter.match(permanent2, game);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,15 +37,13 @@ public final class Suncleanser extends CardImpl {
|
|||
|
||||
// When Suncleanser enters the battlefield, choose one —
|
||||
// • Remove all counters from target creature. It can't have counters put on it for as long as Suncleanser remains on the battlefield.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new RemoveAllCountersPermanentTargetEffect(), false
|
||||
);
|
||||
ability.addEffect(new SuncleanserPreventCountersEffect(false));
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new RemoveAllCountersPermanentTargetEffect());
|
||||
ability.addEffect(new SuncleanserPreventCountersPermanentEffect());
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
|
||||
// • Target opponent loses all counters. That player can't get counters for as long as Suncleanser remains on the battlefield.
|
||||
Mode mode = new Mode(new SuncleanserRemoveCountersPlayerEffect());
|
||||
mode.addEffect(new SuncleanserPreventCountersEffect(true));
|
||||
mode.addEffect(new SuncleanserPreventCountersPlayerEffect());
|
||||
mode.addTarget(new TargetOpponent());
|
||||
ability.addMode(mode);
|
||||
this.addAbility(ability);
|
||||
|
|
@ -88,24 +86,20 @@ class SuncleanserRemoveCountersPlayerEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
|
||||
class SuncleanserPreventCountersEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
class SuncleanserPreventCountersPlayerEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
SuncleanserPreventCountersEffect(boolean player) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
if (player) {
|
||||
staticText = "That player can't get counters for as long as {this} remains on the battlefield.";
|
||||
} else {
|
||||
staticText = "It can't have counters put on it for as long as {this} remains on the battlefield";
|
||||
}
|
||||
SuncleanserPreventCountersPlayerEffect() {
|
||||
super(Duration.UntilSourceLeavesBattlefield, Outcome.Detriment);
|
||||
staticText = "That player can't get counters for as long as {this} remains on the battlefield.";
|
||||
}
|
||||
|
||||
private SuncleanserPreventCountersEffect(final SuncleanserPreventCountersEffect effect) {
|
||||
private SuncleanserPreventCountersPlayerEffect(final SuncleanserPreventCountersPlayerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuncleanserPreventCountersEffect copy() {
|
||||
return new SuncleanserPreventCountersEffect(this);
|
||||
public SuncleanserPreventCountersPlayerEffect copy() {
|
||||
return new SuncleanserPreventCountersPlayerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -126,3 +120,35 @@ class SuncleanserPreventCountersEffect extends ContinuousRuleModifyingEffectImpl
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SuncleanserPreventCountersPermanentEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
SuncleanserPreventCountersPermanentEffect() {
|
||||
super(Duration.UntilSourceLeavesBattlefield, Outcome.Detriment);
|
||||
staticText = "It can't have counters put on it for as long as {this} remains on the battlefield";
|
||||
}
|
||||
|
||||
private SuncleanserPreventCountersPermanentEffect(final SuncleanserPreventCountersPermanentEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuncleanserPreventCountersPermanentEffect copy() {
|
||||
return new SuncleanserPreventCountersPermanentEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAN_ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
return true;
|
||||
}
|
||||
discard();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.ruleModifying.CantHaveCountersSourceEffect;
|
||||
|
|
@ -10,16 +8,16 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class Tatterkite extends CardImpl {
|
||||
|
||||
public Tatterkite(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
|
||||
this.subtype.add(SubType.SCARECROW);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(1);
|
||||
|
|
@ -29,7 +27,6 @@ public final class Tatterkite extends CardImpl {
|
|||
|
||||
// Tatterkite can't have counters put on it.
|
||||
this.addAbility(new SimpleStaticAbility(new CantHaveCountersSourceEffect()));
|
||||
|
||||
}
|
||||
|
||||
private Tatterkite(final Tatterkite card) {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ public final class LorwynEclipsed extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Bloom Tender", 324, Rarity.MYTHIC, mage.cards.b.BloomTender.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Bloom Tender", 390, Rarity.MYTHIC, mage.cards.b.BloomTender.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Bloom Tender", 400, Rarity.MYTHIC, mage.cards.b.BloomTender.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Blossombind", 45, Rarity.COMMON, mage.cards.b.Blossombind.class));
|
||||
cards.add(new SetCardInfo("Blossoming Defense", 167, Rarity.UNCOMMON, mage.cards.b.BlossomingDefense.class));
|
||||
cards.add(new SetCardInfo("Boggart Cursecrafter", 206, Rarity.UNCOMMON, mage.cards.b.BoggartCursecrafter.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Boggart Cursecrafter", 331, Rarity.UNCOMMON, mage.cards.b.BoggartCursecrafter.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
|
||||
package org.mage.test.cards.rules;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
|
@ -25,28 +21,19 @@ public class MeliraSylvokOutcastTest extends CardTestPlayerBase {
|
|||
// You can't get poison counters.
|
||||
// Creatures you control can't have -1/-1 counters placed on them.
|
||||
// Creatures your opponents control lose infect.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Melira, Sylvok Outcast", 2); // 2/2
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Melira, Sylvok Outcast"); // 2/2
|
||||
// {T}: Add {G}.
|
||||
// Put a -1/-1 counter on Devoted Druid: Untap Devoted Druid.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Devoted Druid", 1); // 0/2
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Put a -1/-1 counter on");
|
||||
checkPlayableAbility("can't put counters", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", false);
|
||||
}
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
@Test
|
||||
public void testBlight() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Gristle Glutton");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Melira, Sylvok Outcast");
|
||||
|
||||
// TODO: improve PutCountersSourceCost, so it can find real playable ability here instead restriction
|
||||
try {
|
||||
execute();
|
||||
Assert.fail("must throw exception on execute");
|
||||
} catch (Throwable e) {
|
||||
if (!e.getMessage().contains("Put a -1/-1 counter on")) {
|
||||
Assert.fail("Needed error about not being able to use the Devoted Druid's -1/-1 ability, but got:\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
assertPowerToughness(playerA, "Devoted Druid", 0, 2);
|
||||
assertCounterCount("Devoted Druid", CounterType.M1M1, 0);
|
||||
assertTapped("Devoted Druid", true); // Because untapping can't be paid
|
||||
checkPlayableAbility("can't put counters", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T},", false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ package org.mage.test.cards.single.shm;
|
|||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
|
@ -46,24 +44,10 @@ public class DevotedDruidTest extends CardTestPlayerBase {
|
|||
// ...
|
||||
// (2018-12-07)
|
||||
|
||||
//checkPlayableAbility("can't put counters", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Put a -1/-1", false);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Put a -1/-1");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
// TODO: improve PutCountersSourceCost, so it can find real playable ability here instead restriction
|
||||
try {
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
Assert.fail("must throw exception on execute");
|
||||
} catch (Throwable e) {
|
||||
if (!e.getMessage().contains("Put a -1/-1")) {
|
||||
Assert.fail("Needed error about not being able to use the Devoted Druid's -1/-1 ability, but got:\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
checkPlayableAbility("can't put counters", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Put a -1/-1", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: must fix, see #13583
|
||||
public void test_PutCounter_ModifiedToZeroCounters() {
|
||||
// {T}: Add {G}.
|
||||
// Put a -1/-1 counter on this creature: Untap this creature.
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import mage.abilities.costs.Cost;
|
|||
import mage.abilities.costs.CostImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.CanHaveCounterAddedPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -19,6 +20,12 @@ import java.util.UUID;
|
|||
*/
|
||||
public class BlightCost extends CostImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(new CanHaveCounterAddedPredicate(CounterType.M1M1));
|
||||
}
|
||||
|
||||
private int amount;
|
||||
|
||||
public BlightCost(int amount) {
|
||||
|
|
@ -45,7 +52,7 @@ public class BlightCost extends CostImpl {
|
|||
public static boolean canBlight(UUID controllerId, Game game, Ability source) {
|
||||
return game
|
||||
.getBattlefield()
|
||||
.contains(StaticFilters.FILTER_CONTROLLED_CREATURE, controllerId, source, game, 1);
|
||||
.contains(filter, controllerId, source, game, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -56,12 +63,10 @@ public class BlightCost extends CostImpl {
|
|||
}
|
||||
|
||||
public static Permanent doBlight(Player player, int amount, Game game, Ability source) {
|
||||
if (player == null || amount < 1 || !game.getBattlefield().contains(
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE, player.getId(), source, game, 1
|
||||
)) {
|
||||
if (player == null || amount < 1 || !canBlight(player.getId(), game, source)) {
|
||||
return null;
|
||||
}
|
||||
TargetPermanent target = new TargetControlledCreaturePermanent();
|
||||
TargetPermanent target = new TargetPermanent(filter);
|
||||
target.withNotTarget(true);
|
||||
target.withChooseHint("to put a -1/-1 counter on");
|
||||
player.choose(Outcome.UnboostCreature, target, source, game);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ public class PayLoyaltyCost extends CostImpl {
|
|||
}
|
||||
}
|
||||
|
||||
return planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + loyaltyCost >= 0 && planeswalker.canLoyaltyBeUsed(game);
|
||||
return planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + loyaltyCost >= 0
|
||||
&& planeswalker.canLoyaltyBeUsed(game)
|
||||
&& (loyaltyCost <= 0 || planeswalker.canHaveCounterAdded(CounterType.LOYALTY, game, source));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -61,15 +63,19 @@ public class PayLoyaltyCost extends CostImpl {
|
|||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Permanent planeswalker = game.getPermanent(source.getSourceId());
|
||||
if (planeswalker != null && planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + amount >= 0 && planeswalker.canLoyaltyBeUsed(game)) {
|
||||
if (amount > 0) {
|
||||
planeswalker.addCounters(CounterType.LOYALTY.createInstance(amount), source.getControllerId(), ability, game, false);
|
||||
} else if (amount < 0) {
|
||||
planeswalker.removeCounters(CounterType.LOYALTY.getName(), Math.abs(amount), source, game);
|
||||
}
|
||||
planeswalker.addLoyaltyUsed();
|
||||
this.paid = true;
|
||||
if (planeswalker == null
|
||||
|| planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + amount < 0
|
||||
|| !planeswalker.canLoyaltyBeUsed(game)
|
||||
|| (amount > 0 && !planeswalker.canHaveCounterAdded(CounterType.LOYALTY, game, source))) {
|
||||
return paid;
|
||||
}
|
||||
if (amount > 0) {
|
||||
planeswalker.addCounters(CounterType.LOYALTY.createInstance(amount), source.getControllerId(), ability, game, false);
|
||||
} else if (amount < 0) {
|
||||
planeswalker.removeCounters(CounterType.LOYALTY.getName(), Math.abs(amount), source, game);
|
||||
}
|
||||
planeswalker.addLoyaltyUsed();
|
||||
this.paid = true;
|
||||
return paid;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import mage.counters.Counter;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -28,15 +29,18 @@ public class PutCountersSourceCost extends CostImpl {
|
|||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
// TODO: implement permanent.canAddCounters with replacement events check, see tests with Devoted Druid
|
||||
return true;
|
||||
return Optional
|
||||
.ofNullable(source.getSourcePermanentIfItStillExists(game))
|
||||
.filter(permanent -> permanent.canHaveCounterAdded(counter, game, source))
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
this.paid = permanent.addCounters(counter, controllerId, ability, game, false);
|
||||
permanent.addCounters(counter, controllerId, ability, game, false);
|
||||
this.paid = true;
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ import mage.abilities.costs.Cost;
|
|||
import mage.abilities.costs.CostImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.permanent.CanHaveCounterAddedPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -20,12 +22,19 @@ public class PutCountersTargetCost extends CostImpl {
|
|||
|
||||
private final Counter counter;
|
||||
|
||||
public PutCountersTargetCost(Counter counter){
|
||||
this(counter, new TargetControlledCreaturePermanent());
|
||||
private static FilterControlledPermanent makeFilter(FilterControlledPermanent filter, Counter counter) {
|
||||
FilterControlledPermanent newFilter = filter.copy();
|
||||
newFilter.add(new CanHaveCounterAddedPredicate(counter));
|
||||
return newFilter;
|
||||
}
|
||||
|
||||
public PutCountersTargetCost(Counter counter, TargetControlledPermanent target) {
|
||||
public PutCountersTargetCost(Counter counter) {
|
||||
this(counter, StaticFilters.FILTER_CONTROLLED_CREATURE);
|
||||
}
|
||||
|
||||
public PutCountersTargetCost(Counter counter, FilterControlledPermanent filter) {
|
||||
this.counter = counter.copy();
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(makeFilter(filter, counter));
|
||||
target.withNotTarget(true);
|
||||
this.addTarget(target);
|
||||
this.text = "put " + counter.getDescription() + " on " + target.getDescription();
|
||||
|
|
@ -40,6 +49,11 @@ public class PutCountersTargetCost extends CostImpl {
|
|||
return new PutCountersTargetCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return canChooseOrAlreadyChosen(ability, source, controllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(ability.getControllerId());
|
||||
|
|
@ -49,15 +63,12 @@ public class PutCountersTargetCost extends CostImpl {
|
|||
for (UUID targetId : this.getTargets().get(0).getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
paid = false;
|
||||
return paid;
|
||||
}
|
||||
paid |= permanent.addCounters(counter, controllerId, ability, game);
|
||||
permanent.addCounters(counter, controllerId, ability, game);
|
||||
paid = true;
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return canChooseOrAlreadyChosen(ability, source, controllerId, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
package mage.abilities.effects.common.ruleModifying;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class CantHaveCountersAllEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
private final FilterPermanent filter;
|
||||
private final CounterType counterType;
|
||||
|
||||
public CantHaveCountersAllEffect(FilterPermanent filter, CounterType counterType) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
this.filter = filter;
|
||||
this.counterType = counterType;
|
||||
staticText = filter.getMessage() + " can't have " +
|
||||
(counterType != null ? counterType.getName() + ' ' : "") +
|
||||
"counters put on them";
|
||||
}
|
||||
|
||||
protected CantHaveCountersAllEffect(final CantHaveCountersAllEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
this.counterType = effect.counterType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CantHaveCountersAllEffect copy() {
|
||||
return new CantHaveCountersAllEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAN_ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (counterType != null && !counterType.getName().equals(event.getData())) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent == null) {
|
||||
permanent = game.getPermanentEntering(event.getTargetId());
|
||||
}
|
||||
return permanent != null && filter.match(permanent, source.getControllerId(), source, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
|
||||
package mage.abilities.effects.common.ruleModifying;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -10,6 +7,8 @@ import mage.constants.Outcome;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Styxo
|
||||
*/
|
||||
|
|
@ -31,15 +30,11 @@ public class CantHaveCountersSourceEffect extends ContinuousRuleModifyingEffectI
|
|||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ADD_COUNTERS;
|
||||
return event.getType() == GameEvent.EventType.CAN_ADD_COUNTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
UUID sourceId = source != null ? source.getSourceId() : null;
|
||||
if (sourceId != null) {
|
||||
return sourceId.equals(event.getTargetId());
|
||||
}
|
||||
return false;
|
||||
return source != null && Objects.equals(source.getSourceId(), event.getTargetId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -758,8 +758,11 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters) {
|
||||
if (this instanceof Permanent && !((Permanent) this).isPhasedIn()) {
|
||||
return false;
|
||||
if (this instanceof Permanent) {
|
||||
Permanent permanent = (Permanent) this;
|
||||
if (!permanent.isPhasedIn() || !permanent.canHaveCounterAdded(counter, game, source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean returnCode = true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package mage.filter.predicate.permanent;
|
||||
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class CanHaveCounterAddedPredicate implements ObjectSourcePlayerPredicate<Permanent> {
|
||||
|
||||
private final CounterType counterType;
|
||||
|
||||
public CanHaveCounterAddedPredicate(Counter counter) {
|
||||
this(CounterType.findByName(counter.getName()));
|
||||
}
|
||||
|
||||
public CanHaveCounterAddedPredicate(CounterType counterType) {
|
||||
this.counterType = counterType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
||||
return input.getObject().canHaveCounterAdded(counterType, game, input.getSource());
|
||||
}
|
||||
}
|
||||
|
|
@ -546,6 +546,19 @@ public class GameEvent implements Serializable {
|
|||
flag not used for this event
|
||||
*/
|
||||
STAY_ATTACHED,
|
||||
/* CAN_ADD_COUNTERS
|
||||
ADD_COUNTER, COUNTER_ADDED,
|
||||
ADD_COUNTERS, COUNTERS_ADDED,
|
||||
targetId id of the permanent or player getting counter(s)
|
||||
sourceId id of the ability adding them
|
||||
playerId player who is adding the counter(s)
|
||||
amount number of counters being added
|
||||
data name of the counter(s) being added
|
||||
|
||||
NOTE: only use CAN_ADD_COUNTERS to check whether a permanent can have counters added (e.g. for paying a cost),
|
||||
otherwise use ADD_COUNTER/ADD_COUNTERS to modify how many counters are added (e.g. doubling or reducing)
|
||||
*/
|
||||
CAN_ADD_COUNTERS,
|
||||
ADD_COUNTER, COUNTER_ADDED,
|
||||
ADD_COUNTERS, COUNTERS_ADDED,
|
||||
/* REMOVE_COUNTER, REMOVE_COUNTERS, COUNTER_REMOVED, COUNTERS_REMOVED
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import mage.MageObjectReference;
|
|||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameState;
|
||||
|
|
@ -109,6 +111,12 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
boolean canBeSacrificed();
|
||||
|
||||
boolean canHaveAnyCounterAdded(Game game, Ability source);
|
||||
|
||||
boolean canHaveCounterAdded(Counter counter, Game game, Ability source);
|
||||
|
||||
boolean canHaveCounterAdded(CounterType counterType, Game game, Ability source);
|
||||
|
||||
void setCardNumber(String cid);
|
||||
|
||||
void setExpansionSetCode(String expansionSetCode);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import mage.ObjectColor;
|
|||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.RoomAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
|
|
@ -17,7 +18,6 @@ import mage.abilities.hint.HintUtils;
|
|||
import mage.abilities.keyword.*;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.abilities.common.RoomAbility;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
|
|
@ -1867,6 +1867,29 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
return canBeSacrificed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHaveAnyCounterAdded(Game game, Ability source) {
|
||||
return this.canHaveCounterAdded((CounterType) null, 1, game, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHaveCounterAdded(Counter counter, Game game, Ability source) {
|
||||
return this.canHaveCounterAdded(CounterType.findByName(counter.getName()), counter.getCount(), game, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHaveCounterAdded(CounterType counterType, Game game, Ability source) {
|
||||
return this.canHaveCounterAdded(counterType, 1, game, source);
|
||||
}
|
||||
|
||||
protected boolean canHaveCounterAdded(CounterType counterType, int amount, Game game, Ability source) {
|
||||
return !game.replaceEvent(GameEvent.getEvent(
|
||||
EventType.CAN_ADD_COUNTERS, objectId, source,
|
||||
source != null ? source.getControllerId() : game.getActivePlayerId(),
|
||||
counterType != null ? counterType.getName() : "", amount
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPairedCard(MageObjectReference pairedCard) {
|
||||
this.pairedPermanent = pairedCard;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue