[FIN] Implement Gogo, Master of Mimicry (#13686)

* [FIN] Implement Gogo, Master of Mimicry

* add test

* fix text

* move abstract method definition to interface where it belongs
This commit is contained in:
Evan Kranzler 2025-05-27 22:01:53 -04:00 committed by Failure
parent 70b1f23248
commit 56e9986b06
9 changed files with 149 additions and 0 deletions

View file

@ -534,6 +534,10 @@ public interface Ability extends Controllable, Serializable {
boolean canFizzle();
Ability withCanBeCopied(boolean canBeCopied);
boolean canBeCopied();
/**
* Adds a target adjuster to this ability.
* If using a generic adjuster, only use after adding the blueprint target!

View file

@ -83,6 +83,7 @@ public abstract class AbilityImpl implements Ability {
private List<Watcher> watchers = new ArrayList<>(); // access to it by GetWatchers only (it can be overridden by some abilities)
private List<Ability> subAbilities = null;
private boolean canFizzle = true; // for Gilded Drake
private boolean canBeCopied = true;
private TargetAdjuster targetAdjuster = null;
private CostAdjuster costAdjuster = null;
private List<Hint> hints = new ArrayList<>();
@ -129,6 +130,7 @@ public abstract class AbilityImpl implements Ability {
this.flavorWord = ability.flavorWord;
this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter;
this.canFizzle = ability.canFizzle;
this.canBeCopied = ability.canBeCopied;
this.targetAdjuster = ability.targetAdjuster;
this.costAdjuster = ability.costAdjuster;
this.hints = CardUtil.deepCopyObject(ability.hints);
@ -1733,6 +1735,17 @@ public abstract class AbilityImpl implements Ability {
this.canFizzle = canFizzle;
}
@Override
public boolean canBeCopied() {
return canBeCopied;
}
@Override
public Ability withCanBeCopied(boolean canBeCopied) {
this.canBeCopied = canBeCopied;
return this;
}
@Override
public AbilityImpl setTargetAdjuster(TargetAdjuster targetAdjuster) {
if (targetAdjuster instanceof GenericTargetAdjuster && this.getTargets().isEmpty()) {

View file

@ -1169,6 +1169,11 @@ public class Spell extends StackObjectImpl implements Card {
game.fireEvent(new CopiedStackObjectEvent(this, spellCopy, newControllerId));
}
@Override
public boolean canBeCopied() {
return this.getSpellAbility().canBeCopied();
}
@Override
public boolean isAllCreatureTypes(Game game) {
return card.isAllCreatureTypes(game);

View file

@ -718,6 +718,16 @@ public class StackAbility extends StackObjectImpl implements Ability {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public boolean canBeCopied() {
return ability.canBeCopied();
}
@Override
public Ability withCanBeCopied(boolean canBeCopied) {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public void createSingleCopy(UUID newControllerId, StackObjectCopyApplier applier, MageObjectReferencePredicate newTargetFilterPredicate, Game game, Ability source, boolean chooseNewTargets) {
Ability newAbility = this.ability.copy();

View file

@ -40,6 +40,8 @@ public interface StackObject extends MageObject, Controllable {
void createSingleCopy(UUID newControllerId, StackObjectCopyApplier applier, MageObjectReferencePredicate newTargetFilterPredicate, Game game, Ability source, boolean chooseNewTargets);
boolean canBeCopied();
boolean isTargetChanged();
void setTargetChanged(boolean targetChanged);

View file

@ -154,6 +154,9 @@ public abstract class StackObjectImpl implements StackObject {
@Override
public void createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets, int amount, StackObjectCopyApplier applier) {
if (!this.canBeCopied()) {
return;
}
GameEvent gameEvent = new CopyStackObjectEvent(source, this, newControllerId, amount);
if (game.replaceEvent(gameEvent)) {
return;