[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

@ -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();
}
}