Implement [CMM] Hatchery Sliver; fix Replicate ability (#10694)

* Implement [CMM] Hatchery Sliver

* limit ReplicateAbility to only its linked instance

* Add test for multiple instances of replicate

* add another test
This commit is contained in:
xenohedron 2023-08-11 20:41:45 -04:00 committed by GitHub
parent 5468e2f7e5
commit 7839c6cbff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 138 additions and 22 deletions

View file

@ -1,9 +1,7 @@
package mage.abilities.effects.common.continuous;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.ReplicateAbility;
import mage.constants.Duration;
@ -30,22 +28,23 @@ public class EachSpellYouCastHasReplicateEffect extends ContinuousEffectImpl {
private final Cost fixedNewCost;
private final Map<UUID, ReplicateAbility> replicateAbilities = new HashMap<>();
public EachSpellYouCastHasReplicateEffect(FilterSpell filter) {
this(filter, null);
public EachSpellYouCastHasReplicateEffect(FilterSpell filter, String reminderText) {
this(filter, reminderText, null);
}
/**
*
* @param filter Filter used for filtering spells
* @param reminderText Reminder text that will be italicized and added (capitalize and include punctuation)
* @param fixedNewCost Fixed new cost to pay as the replication cost
*/
public EachSpellYouCastHasReplicateEffect(FilterSpell filter, Cost fixedNewCost) {
public EachSpellYouCastHasReplicateEffect(FilterSpell filter, String reminderText, Cost fixedNewCost) {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
this.filter = filter;
this.fixedNewCost = fixedNewCost;
this.staticText = "Each " + this.filter.getMessage() + " you cast has replicate" +
this.staticText = "Each " + this.filter.getMessage() + (this.filter.getMessage().contains("cast") ? "" : " you cast") +
" has replicate" +
(this.fixedNewCost == null ? ". The replicate cost is equal to its mana cost" : ' ' + this.fixedNewCost.getText())
+ ". <i>(When you cast it, copy it for each time you paid its replicate cost. You may choose new targets for the copies.)</i>";
+ ((reminderText != null && !reminderText.isEmpty()) ? (". <i>(" + reminderText + ")</i>") : "");
}
private EachSpellYouCastHasReplicateEffect(final EachSpellYouCastHasReplicateEffect effect) {

View file

@ -18,6 +18,7 @@ import mage.game.stack.StackObject;
import mage.players.Player;
import java.util.Iterator;
import java.util.UUID;
/**
* @author LevelX2
@ -39,7 +40,7 @@ public class ReplicateAbility extends StaticAbility implements OptionalAdditiona
this.additionalCost = new OptionalAdditionalCostImpl(keywordText, reminderTextMana, cost);
this.additionalCost.setRepeatable(true);
setRuleAtTheTop(true);
addSubAbility(new ReplicateTriggeredAbility());
addSubAbility(new ReplicateTriggeredAbility(this.getId()));
}
protected ReplicateAbility(final ReplicateAbility ability) {
@ -131,13 +132,17 @@ public class ReplicateAbility extends StaticAbility implements OptionalAdditiona
class ReplicateTriggeredAbility extends TriggeredAbilityImpl {
public ReplicateTriggeredAbility() {
private UUID replicateId; // need to correspond only to own replicate ability, not any other instances of replicate ability
public ReplicateTriggeredAbility(UUID replicateId) {
super(Zone.STACK, new ReplicateCopyEffect());
this.replicateId = replicateId;
this.setRuleVisible(false);
}
private ReplicateTriggeredAbility(final ReplicateTriggeredAbility ability) {
super(ability);
this.replicateId = ability.replicateId;
}
@Override
@ -164,7 +169,7 @@ class ReplicateTriggeredAbility extends TriggeredAbilityImpl {
return false;
}
for (Ability ability : card.getAbilities(game)) {
if (!(ability instanceof ReplicateAbility) || !ability.isActivated()) {
if (!(ability instanceof ReplicateAbility) || !ability.isActivated() || ability.getId() != replicateId) {
continue;
}
for (Effect effect : this.getEffects()) {