mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +00:00
Added card "Dyad Force Transfer" and its abilities and effects
This commit is contained in:
parent
64ad1f5984
commit
074a4e6411
5 changed files with 234 additions and 5 deletions
|
@ -53,7 +53,7 @@ public class Droidsmith extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Card copy() {
|
public Droidsmith copy() {
|
||||||
return new Droidsmith(this);
|
return new Droidsmith(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,35 @@
|
||||||
package mage.cards.d;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -468,6 +468,12 @@ public final class StaticFilters {
|
||||||
FILTER_OPPONENTS_PERMANENT_NON_LAND.setLockedFilter(true);
|
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();
|
public static final FilterCreaturePermanent FILTER_OPPONENTS_PERMANENT_CREATURE = new FilterOpponentsCreaturePermanent();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -771,21 +777,21 @@ public final class StaticFilters {
|
||||||
FILTER_SPELL_CREATURE.setLockedFilter(true);
|
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 {
|
static {
|
||||||
FILTER_SPELL_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
FILTER_SPELL_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
||||||
FILTER_SPELL_NON_CREATURE.setLockedFilter(true);
|
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 {
|
static {
|
||||||
FILTER_SPELLS_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
FILTER_SPELLS_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
||||||
FILTER_SPELLS_NON_CREATURE.setLockedFilter(true);
|
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 {
|
static {
|
||||||
FILTER_SPELL_A_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
FILTER_SPELL_A_NON_CREATURE.add(Predicates.not(CardType.CREATURE.getPredicate()));
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue