reworked Clockwork creature implementations (fixes #8292)

This commit is contained in:
Evan Kranzler 2021-09-18 11:08:17 -04:00
parent 2c8314932e
commit 2fa76fc7be
9 changed files with 211 additions and 185 deletions

View file

@ -1,7 +1,5 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.EndOfCombatTriggeredAbility;
@ -12,26 +10,23 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.OneShotEffect;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.counters.Counters;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher;
import java.util.UUID;
/** /**
* * @author TheElk801
* @author MarcoMarin
*/ */
public final class ClockworkAvian extends CardImpl { public final class ClockworkAvian extends CardImpl {
@ -52,23 +47,16 @@ public final class ClockworkAvian extends CardImpl {
// At end of combat, if Clockwork Avian attacked or blocked this combat, remove a +1/+0 counter from it. // At end of combat, if Clockwork Avian attacked or blocked this combat, remove a +1/+0 counter from it.
this.addAbility(new ConditionalInterveningIfTriggeredAbility( this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), new EndOfCombatTriggeredAbility(
AttackedOrBlockedThisCombatSourceCondition.instance, new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false
"At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), ), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, " +
new AttackedOrBlockedThisCombatWatcher() "if {this} attacked or blocked this combat, remove a +1/+0 counter from it."
); ), new AttackedOrBlockedThisCombatWatcher());
// {X}, {tap}: Put up to X +1/+0 counters on Clockwork Avian. This ability can't cause the total number of +1/+0 counters on Clockwork Avian to be greater than four. Activate this ability only during your upkeep. // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Avian. This ability can't cause the total number of +1/+0 counters on Clockwork Avian to be greater than four. Activate this ability only during your upkeep.
Ability ability = new ConditionalActivatedAbility( Ability ability = new ConditionalActivatedAbility(
Zone.BATTLEFIELD, Zone.BATTLEFIELD, new ClockworkAvianEffect(),
new AvianAddCountersSourceEffect( new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP)
CounterType.P1P0.createInstance(),
ManacostVariableValue.REGULAR,
true, true
),
new ManaCostsImpl("{X}"),
new IsStepCondition(PhaseStep.UPKEEP),
null
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
@ -84,24 +72,42 @@ public final class ClockworkAvian extends CardImpl {
} }
} }
class AvianAddCountersSourceEffect extends AddCountersSourceEffect { class ClockworkAvianEffect extends OneShotEffect {
public AvianAddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { ClockworkAvianEffect() {
super(counter, amount, informPlayers, putOnCard); super(Outcome.Benefit);
staticText = "Put up to X +1/+0 counters on {this}. This ability can't cause the total number of +1/+0 counters on {this} to be greater than four."; staticText = "put up to X +1/+0 counters on {this}. This ability can't cause " +
"the total number of +1/+0 counters on {this} to be greater than four";
}
private ClockworkAvianEffect(final ClockworkAvianEffect effect) {
super(effect);
}
@Override
public ClockworkAvianEffect copy() {
return new ClockworkAvianEffect(this);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
//record how many counters Player player = game.getPlayer(source.getControllerId());
Counters permCounters = game.getPermanent(source.getSourceId()).getCounters(game); Permanent permanent = source.getSourcePermanentIfItStillExists(game);
int countersWas = permCounters.getCount(CounterType.P1P0); if (player == null || permanent == null) {
if (countersWas < 4) { return false;
super.apply(game, source); }
if (permCounters.getCount(CounterType.P1P0) > 4) { int maxCounters = Integer.min(
permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0) - 4); 4 - permanent.getCounters(game).getCount(CounterType.P1P0), source.getManaCostsToPay().getX()
}//if countersWas < 4 then counter is min(current,4); there is no setCounters function tho );
}//else this is a rare case of an Avian getting boosted by outside sources :) Which is the sole purpose of this if, for the benefit of this rare but not impossible case :p if (maxCounters < 1) {
return true; return false;
}
int toAdd = player.getAmount(
0, maxCounters, "Choose how many +1/+0 counters to put on " + permanent.getName(), game
);
return toAdd > 0 && permanent.addCounters(
CounterType.P1P0.createInstance(toAdd), source.getControllerId(),
source, game, null, true, 4
);
} }
} }

View file

@ -1,7 +1,6 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.EndOfCombatTriggeredAbility;
@ -12,25 +11,22 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.OneShotEffect;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.counters.Counters;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher;
import java.util.UUID;
/** /**
* * @author TheElk801
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/ */
public final class ClockworkBeast extends CardImpl { public final class ClockworkBeast extends CardImpl {
@ -48,23 +44,16 @@ public final class ClockworkBeast extends CardImpl {
// At end of combat, if Clockwork Beast attacked or blocked this combat, remove a +1/+0 counter from it. // At end of combat, if Clockwork Beast attacked or blocked this combat, remove a +1/+0 counter from it.
this.addAbility(new ConditionalInterveningIfTriggeredAbility( this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), new EndOfCombatTriggeredAbility(
AttackedOrBlockedThisCombatSourceCondition.instance, new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false
"At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), ), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, " +
new AttackedOrBlockedThisCombatWatcher() "if {this} attacked or blocked this combat, remove a +1/+0 counter from it."
); ), new AttackedOrBlockedThisCombatWatcher());
// {X}, {tap}: Put up to X +1/+0 counters on Clockwork Beast. This ability can't cause the total number of +1/+0 counters on Clockwork Beast to be greater than seven. Activate this ability only during your upkeep. // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Beast. This ability can't cause the total number of +1/+0 counters on Clockwork Beast to be greater than seven. Activate this ability only during your upkeep.
Ability ability = new ConditionalActivatedAbility( Ability ability = new ConditionalActivatedAbility(
Zone.BATTLEFIELD, Zone.BATTLEFIELD, new ClockworkBeastEffect(),
new BeastAddCountersSourceEffect( new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP)
CounterType.P1P0.createInstance(),
ManacostVariableValue.REGULAR,
true, true
),
new ManaCostsImpl("{X}"),
new IsStepCondition(PhaseStep.UPKEEP),
null
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
@ -80,32 +69,42 @@ public final class ClockworkBeast extends CardImpl {
} }
} }
class BeastAddCountersSourceEffect extends AddCountersSourceEffect { class ClockworkBeastEffect extends OneShotEffect {
public BeastAddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { ClockworkBeastEffect() {
super(counter, amount, informPlayers, putOnCard); super(Outcome.Benefit);
staticText = "Put up to X +1/+0 counters on {this}. This ability can't cause the total number of +1/+0 counters on {this} to be greater than seven."; staticText = "put up to X +1/+0 counters on {this}. This ability can't cause " +
"the total number of +1/+0 counters on {this} to be greater than seven";
} }
@Override private ClockworkBeastEffect(final ClockworkBeastEffect effect) {
public boolean apply(Game game, Ability source) {
Counters permCounters = game.getPermanent(source.getSourceId()).getCounters(game);
int countersWas = permCounters.getCount(CounterType.P1P0);
if (countersWas < 7) {
super.apply(game, source);
if (permCounters.getCount(CounterType.P1P0) > 7) {
permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0) - 7);
}//if countersWas < 7 then counter is min(current,7); there is no setCounters function though
}//else this is a rare case of a Beast getting boosted by outside sources. Which is the sole purpose of this if, for the benefit of this rare but not impossible case
return true;
}
public BeastAddCountersSourceEffect(final BeastAddCountersSourceEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public BeastAddCountersSourceEffect copy() { public ClockworkBeastEffect copy() {
return new BeastAddCountersSourceEffect(this); return new ClockworkBeastEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (player == null || permanent == null) {
return false;
}
int maxCounters = Integer.min(
7 - permanent.getCounters(game).getCount(CounterType.P1P0), source.getManaCostsToPay().getX()
);
if (maxCounters < 1) {
return false;
}
int toAdd = player.getAmount(
0, maxCounters, "Choose how many +1/+0 counters to put on " + permanent.getName(), game
);
return toAdd > 0 && permanent.addCounters(
CounterType.P1P0.createInstance(toAdd), source.getControllerId(),
source, game, null, true, 7
);
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.EndOfCombatTriggeredAbility;
@ -13,28 +11,24 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.OneShotEffect;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.counters.Counters;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher;
import java.util.UUID;
/** /**
* * @author TheElk801
* @author escplan9, MarcoMarin & L_J
*/ */
public final class ClockworkSteed extends CardImpl { public final class ClockworkSteed extends CardImpl {
@ -58,23 +52,16 @@ public final class ClockworkSteed extends CardImpl {
// At end of combat, if Clockwork Steed attacked or blocked this combat, remove a +1/+0 counter from it. // At end of combat, if Clockwork Steed attacked or blocked this combat, remove a +1/+0 counter from it.
this.addAbility(new ConditionalInterveningIfTriggeredAbility( this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), new EndOfCombatTriggeredAbility(
AttackedOrBlockedThisCombatSourceCondition.instance, new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false
"At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), ), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, " +
new AttackedOrBlockedThisCombatWatcher() "if {this} attacked or blocked this combat, remove a +1/+0 counter from it."
); ), new AttackedOrBlockedThisCombatWatcher());
// {X}, {tap}: Put up to X +1/+0 counters on Clockwork Steed. This ability can't cause the total number of +1/+0 counters on Clockwork Steed to be greater than four. Activate this ability only during your upkeep. // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Steed. This ability can't cause the total number of +1/+0 counters on Clockwork Steed to be greater than four. Activate this ability only during your upkeep.
Ability ability = new ConditionalActivatedAbility( Ability ability = new ConditionalActivatedAbility(
Zone.BATTLEFIELD, Zone.BATTLEFIELD, new ClockworkSteedEffect(),
new ClockworkSteedAddCountersSourceEffect( new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP)
CounterType.P1P0.createInstance(),
ManacostVariableValue.REGULAR,
true, true
),
new ManaCostsImpl("{X}"),
new IsStepCondition(PhaseStep.UPKEEP),
null
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
@ -90,24 +77,42 @@ public final class ClockworkSteed extends CardImpl {
} }
} }
class ClockworkSteedAddCountersSourceEffect extends AddCountersSourceEffect { class ClockworkSteedEffect extends OneShotEffect {
public ClockworkSteedAddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { ClockworkSteedEffect() {
super(counter, amount, informPlayers, putOnCard); super(Outcome.Benefit);
staticText = "Put up to X +1/+0 counters on {this}. This ability can't cause the total number of +1/+0 counters on {this} to be greater than four."; staticText = "put up to X +1/+0 counters on {this}. This ability can't cause " +
"the total number of +1/+0 counters on {this} to be greater than four";
}
private ClockworkSteedEffect(final ClockworkSteedEffect effect) {
super(effect);
}
@Override
public ClockworkSteedEffect copy() {
return new ClockworkSteedEffect(this);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
//record how many counters Player player = game.getPlayer(source.getControllerId());
Counters permCounters = game.getPermanent(source.getSourceId()).getCounters(game); Permanent permanent = source.getSourcePermanentIfItStillExists(game);
int countersWas = permCounters.getCount(CounterType.P1P0); if (player == null || permanent == null) {
if (countersWas < 4) { return false;
super.apply(game, source); }
if (permCounters.getCount(CounterType.P1P0) > 4) { int maxCounters = Integer.min(
permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0) - 4); 4 - permanent.getCounters(game).getCount(CounterType.P1P0), source.getManaCostsToPay().getX()
}//if countersWas < 4 then counter is min(current,4); there is no setCounters function tho );
}//else this is a rare case of a Steed getting boosted by outside sources :) Which is the sole purpose of this if, for the benefit of this rare but not impossible case :p if (maxCounters < 1) {
return true; return false;
}
int toAdd = player.getAmount(
0, maxCounters, "Choose how many +1/+0 counters to put on " + permanent.getName(), game
);
return toAdd > 0 && permanent.addCounters(
CounterType.P1P0.createInstance(toAdd), source.getControllerId(),
source, game, null, true, 4
);
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.EndOfCombatTriggeredAbility;
@ -13,27 +11,23 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.OneShotEffect;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.constants.SubType;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.counters.Counters;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class ClockworkSwarm extends CardImpl { public final class ClockworkSwarm extends CardImpl {
@ -62,22 +56,16 @@ public final class ClockworkSwarm extends CardImpl {
// At end of combat, if Clockwork Swarm attacked or blocked this combat, remove a +1/+0 counter from it. // At end of combat, if Clockwork Swarm attacked or blocked this combat, remove a +1/+0 counter from it.
this.addAbility(new ConditionalInterveningIfTriggeredAbility( this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EndOfCombatTriggeredAbility(new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false), new EndOfCombatTriggeredAbility(
AttackedOrBlockedThisCombatSourceCondition.instance, new RemoveCounterSourceEffect(CounterType.P1P0.createInstance()), false
"At end of combat, if {this} attacked or blocked this combat, remove a +1/+0 counter from it."), ), AttackedOrBlockedThisCombatSourceCondition.instance, "At end of combat, " +
new AttackedOrBlockedThisCombatWatcher()); "if {this} attacked or blocked this combat, remove a +1/+0 counter from it."
), new AttackedOrBlockedThisCombatWatcher());
// {X}, {tap}: Put up to X +1/+0 counters on Clockwork Swarm. This ability can't cause the total number of +1/+0 counters on Clockwork Swarm to be greater than four. Activate this ability only during your upkeep. // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Swarm. This ability can't cause the total number of +1/+0 counters on Clockwork Swarm to be greater than four. Activate this ability only during your upkeep.
Ability ability = new ConditionalActivatedAbility( Ability ability = new ConditionalActivatedAbility(
Zone.BATTLEFIELD, Zone.BATTLEFIELD, new ClockworkSwarmEffect(),
new SwarmAddCountersSourceEffect( new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP)
CounterType.P1P0.createInstance(),
ManacostVariableValue.REGULAR,
true, true
),
new ManaCostsImpl("{X}"),
new IsStepCondition(PhaseStep.UPKEEP),
null
); );
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
@ -93,32 +81,42 @@ public final class ClockworkSwarm extends CardImpl {
} }
} }
class SwarmAddCountersSourceEffect extends AddCountersSourceEffect { class ClockworkSwarmEffect extends OneShotEffect {
public SwarmAddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { ClockworkSwarmEffect() {
super(counter, amount, informPlayers, putOnCard); super(Outcome.Benefit);
staticText = "Put up to X +1/+0 counters on {this}. This ability can't cause the total number of +1/+0 counters on {this} to be greater than four."; staticText = "put up to X +1/+0 counters on {this}. This ability can't cause " +
"the total number of +1/+0 counters on {this} to be greater than four";
} }
@Override private ClockworkSwarmEffect(final ClockworkSwarmEffect effect) {
public boolean apply(Game game, Ability source) {
Counters permCounters = game.getPermanent(source.getSourceId()).getCounters(game);
int countersWas = permCounters.getCount(CounterType.P1P0);
if (countersWas < 4) {
super.apply(game, source);
if (permCounters.getCount(CounterType.P1P0) > 4) {
permCounters.removeCounter(CounterType.P1P0, permCounters.getCount(CounterType.P1P0) - 4);
}//if countersWas < 4 then counter is min(current,4); there is no setCounters function though
}//else this is a rare case of a Beast getting boosted by outside sources. Which is the sole purpose of this if, for the benefit of this rare but not impossible case
return true;
}
public SwarmAddCountersSourceEffect(final SwarmAddCountersSourceEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public SwarmAddCountersSourceEffect copy() { public ClockworkSwarmEffect copy() {
return new SwarmAddCountersSourceEffect(this); return new ClockworkSwarmEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (player == null || permanent == null) {
return false;
}
int maxCounters = Integer.min(
4 - permanent.getCounters(game).getCount(CounterType.P1P0), source.getManaCostsToPay().getX()
);
if (maxCounters < 1) {
return false;
}
int toAdd = player.getAmount(
0, maxCounters, "Choose how many +1/+0 counters to put on " + permanent.getName(), game
);
return toAdd > 0 && permanent.addCounters(
CounterType.P1P0.createInstance(toAdd), source.getControllerId(),
source, game, null, true, 4
);
} }
} }

View file

@ -152,6 +152,8 @@ public interface Card extends MageObject {
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect); boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect);
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters);
void removeCounters(String name, int amount, Ability source, Game game); void removeCounters(String name, int amount, Ability source, Game game);
void removeCounters(Counter counter, Ability source, Game game); void removeCounters(Counter counter, Ability source, Game game);

View file

@ -704,12 +704,21 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
@Override @Override
public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect) { public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect) {
return addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect, Integer.MAX_VALUE);
}
public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters) {
boolean returnCode = true; boolean returnCode = true;
GameEvent addingAllEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, source, playerAddingCounters, counter.getName(), counter.getCount()); GameEvent addingAllEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, source, playerAddingCounters, counter.getName(), counter.getCount());
addingAllEvent.setAppliedEffects(appliedEffects); addingAllEvent.setAppliedEffects(appliedEffects);
addingAllEvent.setFlag(isEffect); addingAllEvent.setFlag(isEffect);
if (!game.replaceEvent(addingAllEvent)) { if (!game.replaceEvent(addingAllEvent)) {
int amount = addingAllEvent.getAmount(); int amount;
if (maxCounters < Integer.MAX_VALUE) {
amount = Integer.min(addingAllEvent.getAmount(), maxCounters - this.getCounters(game).getCount(counter.getName()));
} else {
amount = addingAllEvent.getAmount();
}
boolean isEffectFlag = addingAllEvent.getFlag(); boolean isEffectFlag = addingAllEvent.getFlag();
int finalAmount = amount; int finalAmount = amount;
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {

View file

@ -132,8 +132,8 @@ public abstract class ModalDoubleFacesCard extends CardImpl {
} }
@Override @Override
public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect) { public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters) {
return leftHalfCard.addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect); return leftHalfCard.addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect, maxCounters);
} }
@Override @Override

View file

@ -1009,6 +1009,11 @@ public class Spell extends StackObjectImpl implements Card {
return card.addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect); return card.addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect);
} }
@Override
public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters) {
return card.addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect, maxCounters);
}
@Override @Override
public void removeCounters(String name, int amount, Ability source, Game game) { public void removeCounters(String name, int amount, Ability source, Game game) {
card.removeCounters(name, amount, source, game); card.removeCounters(name, amount, source, game);

View file

@ -1,15 +1,15 @@
package mage.watchers.common; package mage.watchers.common;
import java.util.HashSet;
import java.util.Set;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import java.util.HashSet;
import java.util.Set;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public class AttackedOrBlockedThisCombatWatcher extends Watcher { public class AttackedOrBlockedThisCombatWatcher extends Watcher {
@ -23,14 +23,16 @@ public class AttackedOrBlockedThisCombatWatcher extends Watcher {
@Override @Override
public void watch(GameEvent event, Game game) { public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.BEGIN_COMBAT_STEP_PRE) { switch (event.getType()) {
this.getAttackedThisTurnCreatures().clear(); case BEGIN_COMBAT_STEP_PRE:
} this.attackedThisTurnCreatures.clear();
if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) { this.blockedThisTurnCreatures.clear();
this.getAttackedThisTurnCreatures().add(new MageObjectReference(event.getSourceId(), game)); return;
} case ATTACKER_DECLARED:
if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { this.attackedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game));
this.getBlockedThisTurnCreatures().add(new MageObjectReference(event.getSourceId(), game)); return;
case BLOCKER_DECLARED:
this.blockedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game));
} }
} }