forked from External/mage
181 lines
6.6 KiB
Java
181 lines
6.6 KiB
Java
package mage.abilities.effects.common;
|
|
|
|
import mage.MageObject;
|
|
import mage.abilities.Ability;
|
|
import mage.abilities.SpellAbility;
|
|
import mage.abilities.effects.Effect;
|
|
import mage.abilities.effects.OneShotEffect;
|
|
import mage.abilities.keyword.EnchantAbility;
|
|
import mage.constants.Duration;
|
|
import mage.constants.Outcome;
|
|
import mage.constants.SubType;
|
|
import mage.filter.FilterPermanent;
|
|
import mage.filter.StaticFilters;
|
|
import mage.game.Game;
|
|
import mage.game.permanent.Permanent;
|
|
import mage.players.Player;
|
|
import mage.target.Target;
|
|
import mage.target.TargetPermanent;
|
|
import mage.util.functions.ApplyToPermanent;
|
|
import mage.util.functions.EmptyApplyToPermanent;
|
|
|
|
import java.util.UUID;
|
|
|
|
/**
|
|
* @author BetaSteward_at_googlemail.com
|
|
*/
|
|
public class CopyPermanentEffect extends OneShotEffect {
|
|
|
|
private final FilterPermanent filter;
|
|
private final ApplyToPermanent applier;
|
|
private final boolean useTargetOfAbility;
|
|
private Permanent bluePrintPermanent;
|
|
private Duration duration = Duration.Custom;
|
|
|
|
public CopyPermanentEffect() {
|
|
this(StaticFilters.FILTER_PERMANENT_CREATURE);
|
|
}
|
|
|
|
public CopyPermanentEffect(ApplyToPermanent applier) {
|
|
this(StaticFilters.FILTER_PERMANENT_CREATURE, applier);
|
|
}
|
|
|
|
public CopyPermanentEffect(FilterPermanent filter) {
|
|
this(filter, new EmptyApplyToPermanent());
|
|
}
|
|
|
|
public CopyPermanentEffect(FilterPermanent filter, ApplyToPermanent applier) {
|
|
this(filter, applier, false);
|
|
}
|
|
|
|
public CopyPermanentEffect(FilterPermanent filter, ApplyToPermanent applier, boolean useTarget) {
|
|
super(Outcome.Copy);
|
|
this.applier = applier;
|
|
this.filter = filter;
|
|
this.useTargetOfAbility = useTarget;
|
|
this.staticText = "as a copy of any " + filter.getMessage() + " on the battlefield";
|
|
}
|
|
|
|
public CopyPermanentEffect(final CopyPermanentEffect effect) {
|
|
super(effect);
|
|
this.filter = effect.filter.copy();
|
|
this.applier = effect.applier;
|
|
if (effect.bluePrintPermanent != null) {
|
|
this.bluePrintPermanent = effect.bluePrintPermanent.copy();
|
|
}
|
|
this.useTargetOfAbility = effect.useTargetOfAbility;
|
|
this.duration = effect.duration;
|
|
}
|
|
|
|
@Override
|
|
public boolean apply(Game game, Ability source) {
|
|
Player controller = game.getPlayer(source.getControllerId());
|
|
MageObject sourcePermanent = game.getPermanentEntering(source.getSourceId());
|
|
if (sourcePermanent == null) {
|
|
sourcePermanent = game.getObject(source.getSourceId());
|
|
}
|
|
if (controller == null || sourcePermanent == null) {
|
|
return false;
|
|
}
|
|
Permanent copyFromPermanent = null;
|
|
if (useTargetOfAbility) {
|
|
copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
|
} else {
|
|
Target target = new TargetPermanent(filter);
|
|
target.setNotTarget(true);
|
|
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
|
|
controller.choose(Outcome.Copy, target, source.getSourceId(), game);
|
|
copyFromPermanent = game.getPermanent(target.getFirstTarget());
|
|
}
|
|
}
|
|
if (copyFromPermanent == null) {
|
|
return true;
|
|
}
|
|
bluePrintPermanent = game.copyPermanent(duration, copyFromPermanent, sourcePermanent.getId(), source, applier);
|
|
if (bluePrintPermanent == null) {
|
|
return false;
|
|
}
|
|
|
|
// if object is a copy of an aura, it needs to attach again for new target
|
|
if (!bluePrintPermanent.hasSubtype(SubType.AURA, game)) {
|
|
return true;
|
|
}
|
|
//copied from mage.cards.c.CopyEnchantment.java
|
|
|
|
// permanent can be attached (Estrid's Mask) or enchant (Utopia Sprawl)
|
|
// TODO: fix Animate Dead -- it's can't be copied (can't retarget)
|
|
Outcome auraOutcome = Outcome.BoostCreature;
|
|
Target auraTarget = null;
|
|
|
|
// attach - search effect in spell ability (example: cast Utopia Sprawl, cast Estrid's Invocation on it)
|
|
for (Ability ability : bluePrintPermanent.getAbilities()) {
|
|
if (!(ability instanceof SpellAbility)) {
|
|
continue;
|
|
}
|
|
auraOutcome = ability.getEffects().getOutcome(ability);
|
|
for (Effect effect : ability.getEffects()) {
|
|
if (!(effect instanceof AttachEffect)) {
|
|
continue;
|
|
}
|
|
if (bluePrintPermanent.getSpellAbility().getTargets().size() > 0) {
|
|
auraTarget = bluePrintPermanent.getSpellAbility().getTargets().get(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// enchant - search in all abilities (example: cast Estrid's Invocation on enchanted creature by Estrid, the Masked second ability, cast Estrid's Invocation on it)
|
|
if (auraTarget == null) {
|
|
for (Ability ability : bluePrintPermanent.getAbilities()) {
|
|
if (!(ability instanceof EnchantAbility)) {
|
|
continue;
|
|
}
|
|
auraOutcome = ability.getEffects().getOutcome(ability);
|
|
if (ability.getTargets().size() > 0) { // Animate Dead don't have targets
|
|
auraTarget = ability.getTargets().get(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if this is a copy of a copy, the copy's target has been
|
|
* copied and needs to be cleared
|
|
*/
|
|
if (auraTarget == null) {
|
|
return true;
|
|
}
|
|
// clear selected target
|
|
if (auraTarget.getFirstTarget() != null) {
|
|
auraTarget.remove(auraTarget.getFirstTarget());
|
|
}
|
|
|
|
// select new target
|
|
auraTarget.setNotTarget(true);
|
|
if (!controller.choose(auraOutcome, auraTarget, source.getSourceId(), game)) {
|
|
return true;
|
|
}
|
|
UUID targetId = auraTarget.getFirstTarget();
|
|
Permanent targetPermanent = game.getPermanent(targetId);
|
|
Player targetPlayer = game.getPlayer(targetId);
|
|
if (targetPermanent != null) {
|
|
targetPermanent.addAttachment(sourcePermanent.getId(), game);
|
|
} else if (targetPlayer != null) {
|
|
targetPlayer.addAttachment(sourcePermanent.getId(), game);
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public Permanent getBluePrintPermanent() {
|
|
return bluePrintPermanent;
|
|
}
|
|
|
|
@Override
|
|
public CopyPermanentEffect copy() {
|
|
return new CopyPermanentEffect(this);
|
|
}
|
|
|
|
public CopyPermanentEffect setDuration(Duration duration) {
|
|
this.duration = duration;
|
|
return this;
|
|
}
|
|
}
|