foul-magics/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.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;
}
}