[FIC] Implement Tidus, Yuna's Guardian (#13555)

* [FIC] Implement Tidus, Yuna's Guardian

* merge fix
This commit is contained in:
Evan Kranzler 2025-05-23 08:33:50 -04:00 committed by Failure
parent 3444a93342
commit 53532a7f60
11 changed files with 280 additions and 402 deletions

View file

@ -5,21 +5,20 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.EntersWithCountersControlledEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
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.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
@ -28,10 +27,12 @@ import java.util.UUID;
*/
public final class CombineGuildmage extends CardImpl {
private static final FilterPermanent filter1
= new FilterControlledCreaturePermanent("creature you control (to remove a counter from)");
private static final FilterPermanent filter2
= new FilterControlledCreaturePermanent("creature you control (to move a counter to)");
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("another target creature you control");
static {
filter.add(new AnotherTargetPredicate(2));
}
public CombineGuildmage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}");
@ -50,12 +51,10 @@ public final class CombineGuildmage extends CardImpl {
this.addAbility(ability);
// {1}{U}, {T}: Move a +1/+1 counter from target creature you control onto another target creature you control.
ability = new SimpleActivatedAbility(
new CombineGuildmageCounterEffect(), new ManaCostsImpl<>("{1}{U}")
);
ability = new SimpleActivatedAbility(new MoveCounterTargetsEffect(CounterType.P1P1), new ManaCostsImpl<>("{1}{U}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPermanent(filter1));
ability.addTarget(new TargetPermanent(filter2));
ability.addTarget(new TargetControlledCreaturePermanent().withChooseHint("to remove a counter from"));
ability.addTarget(new TargetPermanent(filter).withChooseHint("to move a counter to").setTargetTag(2));
this.addAbility(ability);
}
@ -68,34 +67,3 @@ public final class CombineGuildmage extends CardImpl {
return new CombineGuildmage(this);
}
}
class CombineGuildmageCounterEffect extends OneShotEffect {
CombineGuildmageCounterEffect() {
super(Outcome.Benefit);
staticText = "Move a +1/+1 counter from target creature you control onto another target creature you control.";
}
private CombineGuildmageCounterEffect(final CombineGuildmageCounterEffect effect) {
super(effect);
}
@Override
public CombineGuildmageCounterEffect copy() {
return new CombineGuildmageCounterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent fromPermanent = game.getPermanent(source.getFirstTarget());
Permanent toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (fromPermanent == null || toPermanent == null) {
return false;
}
if (fromPermanent.getCounters(game).getCount(CounterType.P1P1) > 0) {
fromPermanent.removeCounters(CounterType.P1P1.createInstance(), source, game);
toPermanent.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game);
}
return true;
}
}

View file

@ -1,38 +1,41 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class DaghatarTheAdamant extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("a second target creature");
static {
filter.add(new AnotherTargetPredicate(2));
}
public DaghatarTheAdamant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
@ -41,17 +44,18 @@ public final class DaghatarTheAdamant extends CardImpl {
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// Daghatar the Adamant enters the battlefield with four +1/+1 counters on it.
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(4)),
"with four +1/+1 counters on it"));
// {1}{B/G}{B/G}: Move a +1/+1 counter from target creature onto a second target creature.
Ability ability = new SimpleActivatedAbility(new MoveCounterFromTargetToTargetEffect(),new ManaCostsImpl<>("{1}{B/G}{B/G}"));
ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature the +1/+1 counter is moved from")));
ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature the +1/+1 counter is moved to")));
Ability ability = new SimpleActivatedAbility(
new MoveCounterTargetsEffect(CounterType.P1P1), new ManaCostsImpl<>("{1}{B/G}{B/G}")
);
ability.addTarget(new TargetCreaturePermanent().withChooseHint("to remove a counter from"));
ability.addTarget(new TargetPermanent(filter).withChooseHint("to move a counter to").setTargetTag(2));
this.addAbility(ability);
}
private DaghatarTheAdamant(final DaghatarTheAdamant card) {
@ -63,39 +67,3 @@ public final class DaghatarTheAdamant extends CardImpl {
return new DaghatarTheAdamant(this);
}
}
class MoveCounterFromTargetToTargetEffect extends OneShotEffect {
MoveCounterFromTargetToTargetEffect() {
super(Outcome.Detriment);
this.staticText = "Move a +1/+1 counter from target creature onto a second target creature";
}
private MoveCounterFromTargetToTargetEffect(final MoveCounterFromTargetToTargetEffect effect) {
super(effect);
}
@Override
public MoveCounterFromTargetToTargetEffect copy() {
return new MoveCounterFromTargetToTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source);
if (sourceObject != null && controller != null) {
Permanent fromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (fromPermanent != null && fromPermanent.getCounters(game).getCount(CounterType.P1P1) > 0) {
Permanent toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (toPermanent != null) {
fromPermanent.removeCounters(CounterType.P1P1.createInstance(), source, game);
toPermanent.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game);
game.informPlayers(sourceObject.getLogName() + ": Moved a +1/+1 counter from " + fromPermanent.getLogName() +" to " + toPermanent.getLogName());
}
}
return true;
}
return false;
}
}

View file

@ -6,28 +6,19 @@ import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.UntapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
/**
@ -35,6 +26,12 @@ import java.util.UUID;
*/
public final class LeechBonder extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("a second target creature");
static {
filter.add(new AnotherTargetPredicate(2));
}
public LeechBonder(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.MERFOLK);
@ -47,21 +44,11 @@ public final class LeechBonder extends CardImpl {
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(2)), "with two -1/-1 counters on it"));
// {U}, {untap}: Move a counter from target creature onto another target creature.
Ability ability = new SimpleActivatedAbility(new LeechBonderEffect(), new ManaCostsImpl<>("{U}"));
Ability ability = new SimpleActivatedAbility(new MoveCounterTargetsEffect(), new ManaCostsImpl<>("{U}"));
ability.addCost(new UntapSourceCost());
// target 1
TargetCreaturePermanent target1 = new TargetCreaturePermanent(new FilterCreaturePermanent("creature to remove counter from"));
target1.setTargetTag(1);
ability.addTarget(target1);
// target 2
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature to put counter on");
filter.add(new AnotherTargetPredicate(2));
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter);
target2.setTargetTag(2);
ability.addTarget(target2);
ability.addTarget(new TargetCreaturePermanent().withChooseHint("to remove a counter from"));
ability.addTarget(new TargetPermanent(filter).withChooseHint("to move a counter to").setTargetTag(2));
this.addAbility(ability);
}
private LeechBonder(final LeechBonder card) {
@ -73,53 +60,3 @@ public final class LeechBonder extends CardImpl {
return new LeechBonder(this);
}
}
class LeechBonderEffect extends OneShotEffect {
LeechBonderEffect() {
super(Outcome.AIDontUseIt);
this.staticText = "Move a counter from target creature onto a second target creature";
}
private LeechBonderEffect(final LeechBonderEffect effect) {
super(effect);
}
@Override
public LeechBonderEffect copy() {
return new LeechBonderEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent fromPermanent = game.getPermanent(source.getFirstTarget());
Permanent toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (fromPermanent == null
|| toPermanent == null
|| controller == null) {
return false;
}
Set<String> possibleChoices = new LinkedHashSet<>(fromPermanent.getCounters(game).keySet());
if (possibleChoices.isEmpty()) {
return false;
}
Choice choice = new ChoiceImpl(false);
choice.setChoices(possibleChoices);
if (controller.choose(outcome, choice, game)) {
String chosen = choice.getChoice();
if (fromPermanent.getCounters(game).containsKey(chosen)) {
CounterType counterType = CounterType.findByName(chosen);
if (counterType != null) {
Counter counter = counterType.createInstance();
fromPermanent.removeCounters(counterType.getName(), 1, source, game);
toPermanent.addCounters(counter, source.getControllerId(), source, game);
return true;
}
}
}
return false;
}
}

View file

@ -4,29 +4,16 @@ import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
import mage.abilities.mana.ColorlessManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
/**
@ -34,6 +21,12 @@ import java.util.UUID;
*/
public final class NestingGrounds extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("another target");
static {
filter.add(new AnotherTargetPredicate(2));
}
public NestingGrounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
@ -41,19 +34,10 @@ public final class NestingGrounds extends CardImpl {
this.addAbility(new ColorlessManaAbility());
// {1}, {T}: Move a counter from target permanent you control onto another target permanent. Activate this ability only any time you could cast a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new NestingGroundsEffect(), new GenericManaCost(1));
Ability ability = new ActivateAsSorceryActivatedAbility(new MoveCounterTargetsEffect(), new GenericManaCost(1));
ability.addCost(new TapSourceCost());
// target 1
TargetControlledPermanent target1 = new TargetControlledPermanent(new FilterControlledPermanent("permanent to remove counter from"));
target1.setTargetTag(1);
ability.addTarget(target1);
// target 2
FilterPermanent filter = new FilterPermanent("permanent to put counter on");
filter.add(new AnotherTargetPredicate(2));
TargetPermanent target2 = new TargetPermanent(filter);
target2.setTargetTag(2);
ability.addTarget(target2);
ability.addTarget(new TargetControlledPermanent().withChooseHint("to remove a counter from"));
ability.addTarget(new TargetPermanent(filter).withChooseHint("to move a counter to").setTargetTag(2));
this.addAbility(ability);
}
@ -66,59 +50,3 @@ public final class NestingGrounds extends CardImpl {
return new NestingGrounds(this);
}
}
class NestingGroundsEffect extends OneShotEffect {
NestingGroundsEffect() {
super(Outcome.AIDontUseIt);
this.staticText = "Move a counter from target permanent you control onto another target permanent";
}
private NestingGroundsEffect(final NestingGroundsEffect effect) {
super(effect);
}
@Override
public NestingGroundsEffect copy() {
return new NestingGroundsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent fromPermanent = game.getPermanent(source.getFirstTarget());
Permanent toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (fromPermanent == null
|| toPermanent == null
|| controller == null
|| fromPermanent.getCounters(game).size() == 0) {
return false;
}
if (fromPermanent.getCounters(game).size() == 1) {
for (Counter counter : fromPermanent.getCounters(game).values()) {
fromPermanent.removeCounters(counter.getName(), 1, source, game);
toPermanent.addCounters(new Counter(counter.getName()), source.getControllerId(), source, game);
}
return true;
}
Choice choice = new ChoiceImpl(false);
Set<String> possibleChoices = new LinkedHashSet<>(fromPermanent.getCounters(game).keySet());
choice.setChoices(possibleChoices);
choice.setMessage("Choose a counter");
if (controller.choose(outcome, choice, game)) {
String chosen = choice.getChoice();
if (fromPermanent.getCounters(game).containsKey(chosen)) {
CounterType counterType = CounterType.findByName(chosen);
if (counterType != null) {
Counter counter = counterType.createInstance();
fromPermanent.removeCounters(counterType.getName(), 1, source, game);
toPermanent.addCounters(counter, source.getControllerId(), source, game);
return true;
}
}
}
return false;
}
}

View file

@ -1,28 +1,39 @@
package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.effects.common.counter.MoveCountersTargetsEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
import mage.abilities.keyword.BountyAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import java.util.UUID;
/**
*
* @author Styxo
*/
public final class RumorMonger extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("another target creature");
static {
filter.add(new AnotherTargetPredicate(2));
}
public RumorMonger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{R}{G}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}{G}");
this.subtype.add(SubType.ARCONA);
this.subtype.add(SubType.HUNTER);
this.power = new MageInt(3);
@ -34,8 +45,9 @@ public final class RumorMonger extends CardImpl {
this.addAbility(ability);
// <i>Bounty</i> &mdash; Whenever a creature an opponent controls with a bounty counter on it dies, you may move a bounty counter from one target creature to another target creatute.
ability = new BountyAbility(new MoveCountersTargetsEffect(CounterType.BOUNTY, 1), false);
ability.addTarget(new TargetOpponentsCreaturePermanent(2));
ability = new BountyAbility(new MoveCounterTargetsEffect(CounterType.BOUNTY), true);
ability.addTarget(new TargetCreaturePermanent().withChooseHint("to remove a counter from"));
ability.addTarget(new TargetPermanent(filter).setTargetTag(2).withChooseHint("to move a counter to"));
this.addAbility(ability);
}

View file

@ -6,14 +6,15 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.Filter;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterEnchantmentPermanent;
import mage.filter.predicate.ObjectSourcePlayer;
@ -37,9 +38,12 @@ import java.util.UUID;
*/
public final class SimicGuildmage extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("another target creature with the same controller");
private static final FilterEnchantmentPermanent auraFilter = new FilterEnchantmentPermanent("Aura");
static {
filter.add(new AnotherTargetPredicate(2));
filter.add(SameControllerPredicate.instance);
auraFilter.add(SubType.AURA.getPredicate());
}
@ -51,26 +55,15 @@ public final class SimicGuildmage extends CardImpl {
this.toughness = new MageInt(2);
// {1}{G}: Move a +1/+1 counter from target creature onto another target creature with the same controller.
Ability countersAbility = new SimpleActivatedAbility(new MoveCounterFromTargetToTargetEffect(), new ManaCostsImpl<>("{1}{G}"));
TargetCreaturePermanent target = new TargetCreaturePermanent(
new FilterCreaturePermanent("creature (you take counter from)"));
target.setTargetTag(1);
countersAbility.addTarget(target);
FilterCreaturePermanent filter = new FilterCreaturePermanent(
"another target creature with the same controller (counter goes to)");
filter.add(new AnotherTargetPredicate(2));
filter.add(new SameControllerPredicate());
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter);
target2.setTargetTag(2);
countersAbility.addTarget(target2);
Ability countersAbility = new SimpleActivatedAbility(new MoveCounterTargetsEffect(CounterType.P1P1), new ManaCostsImpl<>("{1}{G}"));
countersAbility.addTarget(new TargetCreaturePermanent().withChooseHint("to remove a counter from"));
countersAbility.addTarget(new TargetPermanent(filter).withChooseHint("to move a counter to").setTargetTag(2));
this.addAbility(countersAbility);
// {1}{U}: Attach target Aura enchanting a permanent to another permanent with the same controller.
Ability auraAbility = new SimpleActivatedAbility(new MoveAuraEffect(), new ManaCostsImpl<>("{1}{U}"));
auraAbility.addTarget(new TargetPermanent(auraFilter));
this.addAbility(auraAbility);
}
private SimicGuildmage(final SimicGuildmage card) {
@ -83,68 +76,29 @@ public final class SimicGuildmage extends CardImpl {
}
}
class MoveCounterFromTargetToTargetEffect extends OneShotEffect {
MoveCounterFromTargetToTargetEffect() {
super(Outcome.Detriment);
this.staticText = "Move a +1/+1 counter from target creature onto another target creature with the same controller";
}
private MoveCounterFromTargetToTargetEffect(final MoveCounterFromTargetToTargetEffect effect) {
super(effect);
}
@Override
public MoveCounterFromTargetToTargetEffect copy() {
return new MoveCounterFromTargetToTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent fromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
Permanent toPermanent = null;
if (source.getTargets().size() > 1) {
toPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
}
if (fromPermanent == null || toPermanent == null || !fromPermanent.isControlledBy(toPermanent.getControllerId())) {
return false;
}
fromPermanent.removeCounters(CounterType.P1P1.createInstance(1), source, game);
toPermanent.addCounters(CounterType.P1P1.createInstance(1), source.getControllerId(), source, game);
return true;
}
return false;
}
}
class SameControllerPredicate implements ObjectSourcePlayerPredicate<MageItem> {
enum SameControllerPredicate implements ObjectSourcePlayerPredicate<MageItem> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<MageItem> input, Game game) {
StackObject source = game.getStack().getStackObject(input.getSourceId());
if (source != null) {
if (source.getStackAbility().getTargets().isEmpty()
|| source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) {
return true;
}
Permanent firstTarget = game.getPermanent(
source.getStackAbility().getTargets().get(0).getTargets().get(0));
Permanent inputPermanent = game.getPermanent(input.getObject().getId());
if (firstTarget != null && inputPermanent != null) {
return firstTarget.isControlledBy(inputPermanent.getControllerId());
}
if (source == null
|| source.getStackAbility().getTargets().isEmpty()
|| source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) {
return true;
}
return true;
Permanent firstTarget = game.getPermanent(source.getStackAbility().getTargets().get(0).getTargets().get(0));
Permanent inputPermanent = game.getPermanent(input.getObject().getId());
if (firstTarget == null || inputPermanent == null) {
return true;
}
return firstTarget.isControlledBy(inputPermanent.getControllerId());
}
@Override
public String toString() {
return "Target with the same controller";
}
}
class MoveAuraEffect extends OneShotEffect {

View file

@ -0,0 +1,67 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.MoveCounterTargetsEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TidusYunasGuardian extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("a second target creature you control");
static {
filter.add(new AnotherTargetPredicate(2));
}
public TidusYunasGuardian(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// At the beginning of combat on your turn, you may move a counter from target creature you control onto a second target creature you control.
Ability ability = new BeginningOfCombatTriggeredAbility(new MoveCounterTargetsEffect(), true);
ability.addTarget(new TargetControlledCreaturePermanent().withChooseHint("to take a counter from").setTargetTag(1));
ability.addTarget(new TargetPermanent(filter).withChooseHint("to move a counter to").setTargetTag(2));
this.addAbility(ability);
// Cheer - Whenever one or more creatures you control with counters on them deal combat damage to a player, you may draw a card and proliferate. Do this only once each turn.
ability = new OneOrMoreCombatDamagePlayerTriggeredAbility(
new DrawCardSourceControllerEffect(1), SetTargetPointer.NONE, true
).setDoOnlyOnceEachTurn(true);
ability.addEffect(new ProliferateEffect(false).concatBy("and"));
this.addAbility(ability.withFlavorWord("Cheer"));
}
private TidusYunasGuardian(final TidusYunasGuardian card) {
super(card);
}
@Override
public TidusYunasGuardian copy() {
return new TidusYunasGuardian(this);
}
}

View file

@ -366,6 +366,11 @@ public final class FinalFantasyCommander extends ExpansionSet {
cards.add(new SetCardInfo("The Warring Triad", 99, Rarity.RARE, mage.cards.t.TheWarringTriad.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Thought Vessel", 368, Rarity.COMMON, mage.cards.t.ThoughtVessel.class));
cards.add(new SetCardInfo("Three Visits", 315, Rarity.UNCOMMON, mage.cards.t.ThreeVisits.class));
cards.add(new SetCardInfo("Tidus, Yuna's Guardian", 187, Rarity.MYTHIC, mage.cards.t.TidusYunasGuardian.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tidus, Yuna's Guardian", 205, Rarity.MYTHIC, mage.cards.t.TidusYunasGuardian.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tidus, Yuna's Guardian", 213, Rarity.MYTHIC, mage.cards.t.TidusYunasGuardian.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tidus, Yuna's Guardian", 224, Rarity.MYTHIC, mage.cards.t.TidusYunasGuardian.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tidus, Yuna's Guardian", 5, Rarity.MYTHIC, mage.cards.t.TidusYunasGuardian.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tifa, Martial Artist", 188, Rarity.MYTHIC, mage.cards.t.TifaMartialArtist.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tifa, Martial Artist", 206, Rarity.MYTHIC, mage.cards.t.TifaMartialArtist.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Tifa, Martial Artist", 214, Rarity.MYTHIC, mage.cards.t.TifaMartialArtist.class, NON_FULL_USE_VARIOUS));

View file

@ -20,7 +20,11 @@ public class OneOrMoreCombatDamagePlayerTriggeredAbility extends OneOrMoreDamage
}
public OneOrMoreCombatDamagePlayerTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) {
this(Zone.BATTLEFIELD, effect, StaticFilters.FILTER_PERMANENT_CREATURES, setTargetPointer, false);
this(effect, setTargetPointer, false);
}
public OneOrMoreCombatDamagePlayerTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer, boolean optional) {
this(Zone.BATTLEFIELD, effect, StaticFilters.FILTER_PERMANENT_CREATURES, setTargetPointer, optional);
}
public OneOrMoreCombatDamagePlayerTriggeredAbility(Zone zone, Effect effect, FilterCreaturePermanent filter,

View file

@ -0,0 +1,112 @@
package mage.abilities.effects.common.counter;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.EachTargetPointer;
import mage.util.RandomUtil;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Styxo
*/
public class MoveCounterTargetsEffect extends OneShotEffect {
private final CounterType counterType;
public MoveCounterTargetsEffect() {
this((CounterType) null);
}
public MoveCounterTargetsEffect(CounterType counterType) {
super(Outcome.Detriment);
this.counterType = counterType;
this.setTargetPointer(new EachTargetPointer());
}
protected MoveCounterTargetsEffect(final MoveCounterTargetsEffect effect) {
super(effect);
this.counterType = effect.counterType;
}
@Override
public MoveCounterTargetsEffect copy() {
return new MoveCounterTargetsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = this
.getTargetPointer()
.getTargets(game, source)
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (permanents.size() < 2) {
return false;
}
Permanent fromPermanent = permanents.get(0);
if (counterType != null && !fromPermanent.getCounters(game).containsKey(counterType)) {
return false;
}
CounterType typeToRemove;
if (counterType == null) {
Set<String> types = new HashSet<>(fromPermanent.getCounters(game).keySet());
switch (types.size()) {
case 0:
return false;
case 1:
typeToRemove = CounterType.findByName(RandomUtil.randomFromCollection(types));
break;
default:
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Choice choice = new ChoiceImpl(true);
choice.setChoices(types);
choice.setMessage("Choose a type of counter to move");
player.choose(Outcome.BoostCreature, choice, game);
typeToRemove = CounterType.findByName(choice.getChoice());
}
} else {
typeToRemove = counterType;
}
if (typeToRemove == null) {
return false;
}
Permanent toPermanent = permanents.get(1);
if (!toPermanent.addCounters(typeToRemove.createInstance(), source, game)) {
return false;
}
fromPermanent.removeCounters(typeToRemove.createInstance(), source, game);
return true;
}
@Override
public String getText(Mode mode) {
if (!staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder("move ");
sb.append(Optional
.ofNullable(counterType)
.map(c -> counterType.getArticle() + ' ' + counterType.getName())
.orElse("a"));
sb.append(" counter from target ");
sb.append(mode.getTargets().get(0).getDescription());
sb.append(" onto ");
sb.append(mode.getTargets().get(1).getDescription());
return sb.toString();
}
}

View file

@ -1,77 +0,0 @@
package mage.abilities.effects.common.counter;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* @author Styxo
*/
public class MoveCountersTargetsEffect extends OneShotEffect {
private final CounterType counterType;
private final int amount;
public MoveCountersTargetsEffect(CounterType counterType, int amount) {
super(Outcome.Detriment);
this.counterType = counterType;
this.amount = amount;
}
protected MoveCountersTargetsEffect(final MoveCountersTargetsEffect effect) {
super(effect);
this.counterType = effect.counterType;
this.amount = effect.amount;
}
@Override
public MoveCountersTargetsEffect copy() {
return new MoveCountersTargetsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent removeTargetCreature = game.getPermanent(getTargetPointer().getTargets(game, source).get(0));
Permanent addTargetCreature = game.getPermanent(getTargetPointer().getTargets(game, source).get(1));
if (removeTargetCreature != null && addTargetCreature != null && removeTargetCreature.getCounters(game).getCount(counterType) >= amount) {
removeTargetCreature.removeCounters(counterType.createInstance(amount), source, game);
addTargetCreature.addCounters(counterType.createInstance(amount), source.getControllerId(), source, game);
if (!game.isSimulation()) {
game.informPlayers("Moved " + amount + ' ' + counterType.getName() + " counter" + (amount > 1 ? "s" : "") + " from " + removeTargetCreature.getLogName() + " to " + addTargetCreature.getLogName());
}
return true;
}
return false;
}
@Override
public String getText(Mode mode) {
if (!staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder("move ");
if (amount > 1) {
sb.append(amount);
} else {
sb.append('a');
}
sb.append(' ');
sb.append(counterType.getName());
sb.append(" counter");
if (amount > 1) {
sb.append("s ");
} else {
sb.append(' ');
}
sb.append("from one target creature to another target creature");
return sb.toString();
}
}