Added card "Dyad Force Transfer" and its abilities and effects

This commit is contained in:
Daniel Eberhard 2022-12-14 14:05:01 +01:00
parent 64ad1f5984
commit 074a4e6411
5 changed files with 234 additions and 5 deletions

View file

@ -53,7 +53,7 @@ public class Droidsmith extends CardImpl {
}
@Override
public Card copy() {
public Droidsmith copy() {
return new Droidsmith(this);
}
}

View file

@ -1,4 +1,35 @@
package mage.cards.d;
public class DyadForceTransfer {
import mage.abilities.effects.common.continuous.GainControlAndUntapTargetEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import java.util.UUID;
public class DyadForceTransfer extends CardImpl {
public DyadForceTransfer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
//Gain control of target noncreature permanent until end of turn. Untap it.
this.getSpellAbility().addEffect(new GainControlAndUntapTargetEffect(Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetPermanent(1, 1,
StaticFilters.FILTER_PERMANENT_NON_CREATURE));
//Scry 3.
this.getSpellAbility().addEffect(new ScryEffect(3, true));
}
public DyadForceTransfer(DyadForceTransfer card) {
super(card);
}
@Override
public DyadForceTransfer copy() {
return new DyadForceTransfer(this);
}
}

View file

@ -0,0 +1,159 @@
package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author Merlingilb
*/
public class GainControlAndUntapTargetEffect extends ContinuousEffectImpl {
protected UUID controllingPlayerId;
private boolean fixedControl;
private boolean firstControlChange = true;
private final Condition condition;
public GainControlAndUntapTargetEffect(Duration duration) {
this(duration, false, null);
}
/**
* @param duration
* @param fixedControl Controlling player is fixed even if the controller of
* the ability changes later
*/
public GainControlAndUntapTargetEffect(Duration duration, boolean fixedControl) {
this(duration, fixedControl, null);
}
/**
* @param duration
* @param controllingPlayerId Player that controls the target creature
*/
public GainControlAndUntapTargetEffect(Duration duration, UUID controllingPlayerId) {
this(duration, true, controllingPlayerId);
}
public GainControlAndUntapTargetEffect(Duration duration, boolean fixedControl, UUID controllingPlayerId) {
this(duration, fixedControl, controllingPlayerId, null);
}
public GainControlAndUntapTargetEffect(Duration duration, boolean fixedControl, UUID controllingPlayerId, Condition condition) {
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
this.controllingPlayerId = controllingPlayerId;
this.fixedControl = fixedControl;
this.condition = condition;
}
public GainControlAndUntapTargetEffect(final GainControlAndUntapTargetEffect effect) {
super(effect);
this.controllingPlayerId = effect.controllingPlayerId;
this.fixedControl = effect.fixedControl;
this.condition = effect.condition;
}
@Override
public GainControlAndUntapTargetEffect copy() {
return new GainControlAndUntapTargetEffect(this);
}
@Override
public void init(Ability source, Game game) {
if (this.controllingPlayerId == null && fixedControl) {
this.controllingPlayerId = source.getControllerId();
}
super.init(source, game);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
discard(); // controller no longer exists
return false;
}
boolean oneTargetStillExists = false;
for (UUID permanentId : getTargetPointer().getTargets(game, source)) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent == null) {
continue;
}
oneTargetStillExists = true;
if (permanent.isControlledBy(controllingPlayerId)) {
permanent.untap(game);
continue;
}
boolean controlChanged = false;
if (controllingPlayerId != null) {
if (permanent.changeControllerId(controllingPlayerId, game, source)) {
permanent.untap(game);
controlChanged = true;
}
} else {
if (permanent.changeControllerId(source.getControllerId(), game, source)) {
permanent.untap(game);
controlChanged = true;
}
}
if (source instanceof ActivatedAbility
&& firstControlChange && !controlChanged) {
// If it was not possible to get control of target permanent by the activated ability the first time it took place
// the effect failed (e.g. because of Guardian Beast) and must be discarded
// This does not handle correctly multiple targets at once
discard();
}
if (condition != null && !condition.apply(game, source)) {
discard();
}
}
// no valid target exists and the controller is no longer in the game, effect can be discarded
if (!oneTargetStillExists || !controller.isInGame()) {
discard();
}
firstControlChange = false;
return true;
}
@Override
public String getText(Mode mode) {
if (!staticText.isEmpty()) {
return staticText;
}
if (mode.getTargets().isEmpty()) {
return "gain control of target permanent until end of turn. Untap it.";
}
Target target = mode.getTargets().get(0);
StringBuilder sb = new StringBuilder("gain control of ");
if (target.getMaxNumberOfTargets() > 1) {
if (target.getNumberOfTargets() < target.getMaxNumberOfTargets()) {
sb.append("up to ");
}
sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" target ");
} else if (!target.getTargetName().startsWith("another")) {
sb.append("target ");
}
sb.append(mode.getTargets().get(0).getTargetName());
if (!duration.toString().isEmpty()) {
sb.append(' ').append(duration.toString());
}
sb.append("and untap it");
return sb.toString();
}
}

View file

@ -468,6 +468,12 @@ public final class StaticFilters {
FILTER_OPPONENTS_PERMANENT_NON_LAND.setLockedFilter(true);
}
public static final FilterNoncreaturePermanent FILTER_PERMANENT_NON_CREATURE = new FilterNoncreaturePermanent();
static {
FILTER_PERMANENT_NON_CREATURE.setLockedFilter(true);
}
public static final FilterCreaturePermanent FILTER_OPPONENTS_PERMANENT_CREATURE = new FilterOpponentsCreaturePermanent();
static {
@ -771,21 +777,21 @@ public final class StaticFilters {
FILTER_SPELL_CREATURE.setLockedFilter(true);
}
public static final FilterSpell FILTER_SPELL_NON_CREATURE = (FilterSpell) new FilterSpell("noncreature spell");
public static final FilterSpell FILTER_SPELL_NON_CREATURE = new FilterSpell("noncreature spell");
static {
FILTER_SPELL_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
FILTER_SPELL_NON_CREATURE.setLockedFilter(true);
}
public static final FilterSpell FILTER_SPELLS_NON_CREATURE = (FilterSpell) new FilterSpell("noncreature spells");
public static final FilterSpell FILTER_SPELLS_NON_CREATURE = new FilterSpell("noncreature spells");
static {
FILTER_SPELLS_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
FILTER_SPELLS_NON_CREATURE.setLockedFilter(true);
}
public static final FilterSpell FILTER_SPELL_A_NON_CREATURE = (FilterSpell) new FilterSpell("a noncreature spell");
public static final FilterSpell FILTER_SPELL_A_NON_CREATURE = new FilterSpell("a noncreature spell");
static {
FILTER_SPELL_A_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));

View file

@ -0,0 +1,33 @@
package mage.filter.common;
import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
/**
* @author Merlingilb
*/
public class FilterNoncreaturePermanent extends FilterPermanent {
public FilterNoncreaturePermanent() {
this("noncreature permanent");
}
public FilterNoncreaturePermanent(String name) {
super(name);
this.add(Predicates.not(CardType.CREATURE.getPredicate()));
}
public FilterNoncreaturePermanent(final FilterNoncreaturePermanent filter) {
super(filter);
}
@Override
public FilterNoncreaturePermanent copy() {
return new FilterNoncreaturePermanent(this);
}
}