diff --git a/Mage.Sets/src/mage/cards/b/BloodtitheCollector.java b/Mage.Sets/src/mage/cards/b/BloodtitheCollector.java index 4be5304e1eb..5845f5f9b7a 100644 --- a/Mage.Sets/src/mage/cards/b/BloodtitheCollector.java +++ b/Mage.Sets/src/mage/cards/b/BloodtitheCollector.java @@ -31,10 +31,10 @@ public final class BloodtitheCollector extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // When Bloodtithe Collector enters the battlefield, if an opponent lost life this turn, each opponent discards a card. + // When this creature enters, if an opponent lost life this turn, each opponent discards a card. this.addAbility(new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT)), - OpponentsLostLifeCondition.instance, "When {this} enters, " + + OpponentsLostLifeCondition.instance, "When this creature enters, " + "if an opponent lost life this turn, each opponent discards a card." ).addHint(OpponentsLostLifeHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/c/CemeteryTampering.java b/Mage.Sets/src/mage/cards/c/CemeteryTampering.java index 1d79cd569ac..c41f83f6b6f 100644 --- a/Mage.Sets/src/mage/cards/c/CemeteryTampering.java +++ b/Mage.Sets/src/mage/cards/c/CemeteryTampering.java @@ -23,7 +23,7 @@ public final class CemeteryTampering extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); // Hideaway 5 - this.addAbility(new HideawayAbility(5)); + this.addAbility(new HideawayAbility(this, 5)); // At the beginning of your upkeep, you may mill three cards. Then if there are twenty or more cards in your graveyard, you may play the exiled card without paying its mana cost. this.addAbility(new BeginningOfUpkeepTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/c/CollectorsCage.java b/Mage.Sets/src/mage/cards/c/CollectorsCage.java index 76e2dd62285..7a59aa15b8f 100644 --- a/Mage.Sets/src/mage/cards/c/CollectorsCage.java +++ b/Mage.Sets/src/mage/cards/c/CollectorsCage.java @@ -27,7 +27,7 @@ public final class CollectorsCage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}"); // Hideaway 5 - this.addAbility(new HideawayAbility(5)); + this.addAbility(new HideawayAbility(this, 5)); // {1}, {T}: Put a +1/+1 counter on target creature you control. Then if you control three or more creatures with different powers, you may play the exiled card without paying its mana cost. Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/d/DwynensElite.java b/Mage.Sets/src/mage/cards/d/DwynensElite.java index a13e8ac859a..0e030e313fe 100644 --- a/Mage.Sets/src/mage/cards/d/DwynensElite.java +++ b/Mage.Sets/src/mage/cards/d/DwynensElite.java @@ -35,12 +35,12 @@ public final class DwynensElite extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - // When Dwynen's Elite enters the battlefield, if you control another Elf, create a 1/1 green Elf Warrior creature token. + // When this creature enters, if you control another Elf, create a 1/1 green Elf Warrior creature token. TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ElfWarriorToken())); this.addAbility(new ConditionalInterveningIfTriggeredAbility( triggeredAbility, new PermanentsOnTheBattlefieldCondition(filter), - "When {this} enters, if you control another Elf, create a 1/1 green Elf Warrior creature token.")); + "When this creature enters, if you control another Elf, create a 1/1 green Elf Warrior creature token.")); } private DwynensElite(final DwynensElite card) { diff --git a/Mage.Sets/src/mage/cards/f/FightRigging.java b/Mage.Sets/src/mage/cards/f/FightRigging.java index 7ea5ed79be4..105fcedbc3f 100644 --- a/Mage.Sets/src/mage/cards/f/FightRigging.java +++ b/Mage.Sets/src/mage/cards/f/FightRigging.java @@ -37,7 +37,7 @@ public final class FightRigging extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // Hideaway 5 - this.addAbility(new HideawayAbility(5)); + this.addAbility(new HideawayAbility(this, 5)); // At the beginning of combat on your turn, put a +1/+1 counter on target creature you control. Then if you control a creature with power 7 or greater, you may play the exiled card without paying its mana cost. Ability ability = new BeginningOfCombatTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java b/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java index 3a6c64a0c6d..b45be20251f 100644 --- a/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java +++ b/Mage.Sets/src/mage/cards/g/GatekeeperOfMalakir.java @@ -40,10 +40,11 @@ public final class GatekeeperOfMalakir extends CardImpl { // Kicker {B} (You may pay an additional {B} as you cast this spell.) this.addAbility(new KickerAbility("{B}")); - // When Gatekeeper of Malakir enters the battlefield, if it was kicked, target player sacrifices a creature. + // When this creature enters, if it was kicked, target player sacrifices a creature. EntersBattlefieldTriggeredAbility ability = - new EntersBattlefieldTriggeredAbility(new SacrificeEffect(filter, 1, "target player")); - Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, target player sacrifices a creature."); + new EntersBattlefieldTriggeredAbility(new SacrificeEffect(filter, 1, "target player")) + .setTriggerPhrase("When this creature enters, "); + Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When this creature enters, if it was kicked, target player sacrifices a creature."); conditionalAbility.addTarget(new TargetPlayer()); this.addAbility(conditionalAbility); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java b/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java index af531d8cbf6..aee5bf27ee4 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java @@ -34,7 +34,7 @@ public final class GoblinBushwhacker extends CardImpl { // Kicker {R} (You may pay an additional {R} as you cast this spell.) this.addAbility(new KickerAbility("{R}")); - // When Goblin Bushwhacker enters the battlefield, if it was kicked, creatures you control get +1/+0 and gain haste until end of turn. + // When this creature enters, if it was kicked, creatures you control get +1/+0 and gain haste until end of turn. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostControlledEffect(1, 0, Duration.EndOfTurn), false); ability.addEffect(new GainAbilityControlledEffect( HasteAbility.getInstance(), @@ -44,7 +44,7 @@ public final class GoblinBushwhacker extends CardImpl { this.addAbility(new ConditionalInterveningIfTriggeredAbility( ability, KickedCondition.ONCE, - "When {this} enters, " + "When this creature enters, " + "if it was kicked, " + "creatures you control get +1/+0 and gain haste until end of turn." )); diff --git a/Mage.Sets/src/mage/cards/h/HowltoothHollow.java b/Mage.Sets/src/mage/cards/h/HowltoothHollow.java index 0b10e9cf2ce..5dd7b2425f8 100644 --- a/Mage.Sets/src/mage/cards/h/HowltoothHollow.java +++ b/Mage.Sets/src/mage/cards/h/HowltoothHollow.java @@ -34,7 +34,7 @@ public final class HowltoothHollow extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // Hideaway - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); this.addAbility(new EntersBattlefieldTappedAbility()); // {tap}: Add {B}. diff --git a/Mage.Sets/src/mage/cards/m/MosswortBridge.java b/Mage.Sets/src/mage/cards/m/MosswortBridge.java index 1a24640b7f1..2df3317023a 100644 --- a/Mage.Sets/src/mage/cards/m/MosswortBridge.java +++ b/Mage.Sets/src/mage/cards/m/MosswortBridge.java @@ -28,7 +28,7 @@ public final class MosswortBridge extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // Hideaway (This land enters the battlefield tapped. When it does, look at the top four cards of your library, exile one face down, then put the rest on the bottom of your library.) - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); this.addAbility(new EntersBattlefieldTappedAbility()); // {T}: Add {G}. diff --git a/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java b/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java index 80c4f12020b..498c3ca4f47 100644 --- a/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java +++ b/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java @@ -40,10 +40,10 @@ public final class NullpriestOfOblivion extends CardImpl { // Lifelink this.addAbility(LifelinkAbility.getInstance()); - // When Nullpriest of Oblivion enters the battlefield, if it was kicked, return target creature card from your graveyard to the battlefield. + // When this creature enters the battlefield, if it was kicked, return target creature card from your graveyard to the battlefield. Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + + KickedCondition.ONCE, "When this creature enters, if it was kicked, " + "return target creature card from your graveyard to the battlefield." ); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); diff --git a/Mage.Sets/src/mage/cards/r/RabbleRousing.java b/Mage.Sets/src/mage/cards/r/RabbleRousing.java index ba6b3c4b414..a0b5e7188fb 100644 --- a/Mage.Sets/src/mage/cards/r/RabbleRousing.java +++ b/Mage.Sets/src/mage/cards/r/RabbleRousing.java @@ -34,7 +34,7 @@ public final class RabbleRousing extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); // Hideaway 5 - this.addAbility(new HideawayAbility(5)); + this.addAbility(new HideawayAbility(this, 5)); // Whenever you attack with one or more creatures, create that many 1/1 green and white Citizen creature tokens. Then if you control ten or more creatures, you may play the exiled card without paying its mana cost. Ability ability = new AttacksWithCreaturesTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/s/ShelldockIsle.java b/Mage.Sets/src/mage/cards/s/ShelldockIsle.java index 1feb7b775ed..c451b5de043 100644 --- a/Mage.Sets/src/mage/cards/s/ShelldockIsle.java +++ b/Mage.Sets/src/mage/cards/s/ShelldockIsle.java @@ -29,7 +29,7 @@ public final class ShelldockIsle extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // Hideaway - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); this.addAbility(new EntersBattlefieldTappedAbility()); // {tap}: Add {U}. diff --git a/Mage.Sets/src/mage/cards/s/SmugglersBuggy.java b/Mage.Sets/src/mage/cards/s/SmugglersBuggy.java index 7b0c86d4b40..73f3d113536 100644 --- a/Mage.Sets/src/mage/cards/s/SmugglersBuggy.java +++ b/Mage.Sets/src/mage/cards/s/SmugglersBuggy.java @@ -35,7 +35,7 @@ public class SmugglersBuggy extends CardImpl { // Hideaway 4 // (When this artifact enters the battlefield, look at the top four cards of your library, // exile one face down, then put the rest on the bottom in a random order.) - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); // Whenever Smuggler’s Buggy deals combat damage to a player, you may cast the exiled card without paying its mana cost. // If you do, return Smuggler’s Buggy to its owner’s hand. diff --git a/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java b/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java index d8bdf71aedb..c4ec14b8c23 100644 --- a/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java +++ b/Mage.Sets/src/mage/cards/s/SpinerockKnoll.java @@ -32,7 +32,7 @@ public final class SpinerockKnoll extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // Hideaway - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); this.addAbility(new EntersBattlefieldTappedAbility()); // {tap}: Add {R}. diff --git a/Mage.Sets/src/mage/cards/s/StormFleetSpy.java b/Mage.Sets/src/mage/cards/s/StormFleetSpy.java index bf36f77b9be..cf37d6515c4 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetSpy.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetSpy.java @@ -29,11 +29,11 @@ public final class StormFleetSpy extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - // Raid — When Storm Fleet Spy enters the battlefield, if you attacked this turn, draw a card. + // Raid — When this creature enters, if you attacked this turn, draw a card. Ability ability = new ConditionalInterveningIfTriggeredAbility( new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), RaidCondition.instance, - "When {this} enters, if you attacked this turn, draw a card."); + "When this creature enters, if you attacked this turn, draw a card."); ability.setAbilityWord(AbilityWord.RAID); ability.addHint(RaidHint.instance); this.addAbility(ability, new PlayerAttackedWatcher()); diff --git a/Mage.Sets/src/mage/cards/w/WatcherForTomorrow.java b/Mage.Sets/src/mage/cards/w/WatcherForTomorrow.java index 3b3e5e2145b..57b123c4739 100644 --- a/Mage.Sets/src/mage/cards/w/WatcherForTomorrow.java +++ b/Mage.Sets/src/mage/cards/w/WatcherForTomorrow.java @@ -33,7 +33,7 @@ public final class WatcherForTomorrow extends CardImpl { this.toughness = new MageInt(1); // Hideaway - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); this.addAbility(new EntersBattlefieldTappedAbility()); // When Watcher for Tomorrow leaves the battlefield, put the exiled card into its owner's hand. diff --git a/Mage.Sets/src/mage/cards/w/WidespreadThieving.java b/Mage.Sets/src/mage/cards/w/WidespreadThieving.java index ea77d732fa7..42cf54aacce 100644 --- a/Mage.Sets/src/mage/cards/w/WidespreadThieving.java +++ b/Mage.Sets/src/mage/cards/w/WidespreadThieving.java @@ -31,7 +31,7 @@ public final class WidespreadThieving extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // Hideaway 5 - this.addAbility(new HideawayAbility(5)); + this.addAbility(new HideawayAbility(this, 5)); // Whenever you cast a multicolored spell, create a Treasure token. Then you may pay {W}{U}{B}{R}{G}. If you do, you may play the exiled card without paying its mana cost. Ability ability = new SpellCastControllerTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/w/WindbriskHeights.java b/Mage.Sets/src/mage/cards/w/WindbriskHeights.java index 17ed6c5a3aa..84e80166b41 100644 --- a/Mage.Sets/src/mage/cards/w/WindbriskHeights.java +++ b/Mage.Sets/src/mage/cards/w/WindbriskHeights.java @@ -27,7 +27,7 @@ public final class WindbriskHeights extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // Hideaway (This land enters the battlefield tapped. When it does, look at the top four cards of your library, exile one face down, then put the rest on the bottom of your library.) - this.addAbility(new HideawayAbility(4)); + this.addAbility(new HideawayAbility(this, 4)); this.addAbility(new EntersBattlefieldTappedAbility()); // {tap}: Add {W}. diff --git a/Mage.Sets/src/mage/cards/w/Wiretapping.java b/Mage.Sets/src/mage/cards/w/Wiretapping.java index 1b4a563f59f..afbb61fde73 100644 --- a/Mage.Sets/src/mage/cards/w/Wiretapping.java +++ b/Mage.Sets/src/mage/cards/w/Wiretapping.java @@ -28,7 +28,7 @@ public final class Wiretapping extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); // Hideaway 5 - this.addAbility(new HideawayAbility(5)); + this.addAbility(new HideawayAbility(this, 5)); // Whenever you draw your first card during each of your draw steps, draw a card. Then if you have nine or more cards in hand, you may play the exiled card without paying its mana cost. this.addAbility(new WiretappingTriggeredAbility()); diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index fb1776b8f48..892bfadafbe 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -102,7 +102,8 @@ public class VerifyCardDataTest { "shroud", "banding", "flanking", "horsemanship", "legendary landwalk" ); - private static final List doubleWords = new ArrayList<>(); + private static final List doubleWords = new ArrayList<>(); // for inner calc + private static final List etbTriggerPhrases = new ArrayList<>(); // for inner calc static { // numbers @@ -1989,6 +1990,7 @@ public class VerifyCardDataTest { } String refLowerText = ref.text.toLowerCase(Locale.ENGLISH); + String cardLowerText = String.join("\n", card.getRules()).toLowerCase(Locale.ENGLISH); // special check: kicker ability must be in rules if (card.getAbilities().containsClass(MultikickerAbility.class) && card.getRules().stream().noneMatch(rule -> rule.contains("Multikicker"))) { @@ -2048,6 +2050,21 @@ public class VerifyCardDataTest { fail(card, "abilities", "mutate cards aren't implemented and shouldn't be available"); } + // special check: some new creature's ETB must use When this creature enters instead When {this} enters + if (EntersBattlefieldTriggeredAbility.ENABLE_TRIGGER_PHRASE_AUTO_FIX) { + if (etbTriggerPhrases.isEmpty()) { + etbTriggerPhrases.addAll(EntersBattlefieldTriggeredAbility.getPossibleTriggerPhrases()); + Assert.assertTrue(etbTriggerPhrases.get(0).startsWith("when")); + } + if (refLowerText.contains("when")) { + for (String needTriggerPhrase : etbTriggerPhrases) { + if (refLowerText.contains(needTriggerPhrase) && !cardLowerText.contains(needTriggerPhrase)) { + fail(card, "abilities", "wrong creature's ETB trigger phrase, must use: " + needTriggerPhrase); + } + } + } + } + // special check: wrong dies triggers (there are also a runtime check on wrong usage, see isInUseableZoneDiesTrigger) Set ignoredCards = new HashSet<>(); ignoredCards.add("Caller of the Claw"); diff --git a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldTriggeredAbility.java index d0d8c74d401..0a8aeb373d6 100644 --- a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldTriggeredAbility.java @@ -2,15 +2,22 @@ package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.cards.Card; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; +import java.util.Arrays; +import java.util.List; + /** * @author BetaSteward_at_googlemail.com */ public class EntersBattlefieldTriggeredAbility extends TriggeredAbilityImpl { + static public boolean ENABLE_TRIGGER_PHRASE_AUTO_FIX = false; + public EntersBattlefieldTriggeredAbility(Effect effect) { this(effect, false); } @@ -47,4 +54,59 @@ public class EntersBattlefieldTriggeredAbility extends TriggeredAbilityImpl { public EntersBattlefieldTriggeredAbility copy() { return new EntersBattlefieldTriggeredAbility(this); } + + @Override + public EntersBattlefieldTriggeredAbility setTriggerPhrase(String triggerPhrase) { + super.setTriggerPhrase(triggerPhrase); + return this; + } + + /** + * Find description of "{this}" like "this creature" + */ + static public String getThisObjectDescription(Card card) { + // prepare {this} description + + // short names like Aatchik for Aatchik, Emerald Radian + // except: Mu Yanling, Wind Rider (maybe related to spaces in name) + List parts = Arrays.asList(card.getName().split(",")); + if (parts.size() > 1 && !parts.get(0).contains(" ")) { + return parts.get(0); + } + + // some types have priority, e.g. Vehicle instead artifact, example: Boommobile + if (card.getSubtype().contains(SubType.VEHICLE)) { + return "this Vehicle"; + } + if (card.getSubtype().contains(SubType.AURA)) { + return "this Aura"; + } + + // by priority + if (card.isCreature()) { + return "this creature"; + } else if (card.isPlaneswalker()) { + return "this planeswalker"; + } else if (card.isLand()) { + return "this land"; + } else if (card.isEnchantment()) { + return "this enchantment"; + } else if (card.isArtifact()) { + return "this artifact"; + } else { + return "this permanent"; + } + } + + public static List getPossibleTriggerPhrases() { + // for verify tests - must be same list as above (only {this} relates phrases) + return Arrays.asList( + "when this creature enters", + "when this planeswalker enters", + "when this land enters", + "when this enchantment enters", + "when this artifact enters", + "when this permanent enters" + ); + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java b/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java index 8e4ea99d7fb..d6baf07740f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ChampionAbility.java @@ -47,6 +47,7 @@ import java.util.UUID; public class ChampionAbility extends StaticAbility { protected final String objectDescription; + protected final String etbObjectDescription; /** * Champion one or more creature types or if the subtype array is empty @@ -59,6 +60,8 @@ public class ChampionAbility extends StaticAbility { public ChampionAbility(Card card, SubType... subtypes) { super(Zone.BATTLEFIELD, null); + this.etbObjectDescription = EntersBattlefieldTriggeredAbility.getThisObjectDescription(card); + List subTypes = Arrays.asList(subtypes); FilterControlledPermanent filter; switch (subTypes.size()) { @@ -105,6 +108,7 @@ public class ChampionAbility extends StaticAbility { protected ChampionAbility(final ChampionAbility ability) { super(ability); this.objectDescription = ability.objectDescription; + this.etbObjectDescription = ability.etbObjectDescription; } @Override @@ -115,7 +119,7 @@ public class ChampionAbility extends StaticAbility { @Override public String getRule() { return "Champion " + CardUtil.addArticle(objectDescription) - + " (When this enters the battlefield, sacrifice it unless you exile another " + objectDescription + + " (When " + etbObjectDescription + " enters, sacrifice it unless you exile another " + objectDescription + " you control. When this leaves the battlefield, that card returns to the battlefield.)"; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java b/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java index 5e08f7bef1a..4142d96a8eb 100644 --- a/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java @@ -36,21 +36,25 @@ import java.util.*; public class HideawayAbility extends EntersBattlefieldTriggeredAbility { private final int amount; + private final String etbObjectDescription; - public HideawayAbility(int amount) { + public HideawayAbility(Card card, int amount) { super(new HideawayExileEffect(amount)); this.amount = amount; this.addWatcher(new HideawayWatcher()); + + this.etbObjectDescription = EntersBattlefieldTriggeredAbility.getThisObjectDescription(card); } private HideawayAbility(final HideawayAbility ability) { super(ability); this.amount = ability.amount; + this.etbObjectDescription = ability.etbObjectDescription; } @Override public String getRule() { - return "Hideaway " + this.amount + " (When this permanent enters the battlefield, look at the top " + return "Hideaway " + this.amount + " (When " + this.etbObjectDescription + " enters, look at the top " + CardUtil.numberToText(this.amount) + " cards of your library, exile one face down, " + "then put the rest on the bottom of your library in a random order.)"; } diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index c2039c9e24f..e6c7aa4b9ae 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -4,6 +4,7 @@ import mage.MageObject; import mage.MageObjectImpl; import mage.Mana; import mage.abilities.*; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.HasSubtypesSourceEffect; import mage.abilities.keyword.ChangelingAbility; @@ -344,19 +345,18 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } } - // rules fix: workaround to add text auto-replacement for creature's ETB - if (this.isCreature() && ability.getRule().startsWith("When {this} enters") && ability instanceof TriggeredAbility) { - TriggeredAbility triggeredAbility = ((TriggeredAbility) ability); - if (triggeredAbility.getTriggerPhrase() != null) { - // TODO: delete or enable after wizards update all cards, not last sets only, see https://github.com/magefree/mage/issues/12791 - //triggeredAbility.setTriggerPhrase(triggeredAbility.getTriggerPhrase().replace("{this}", "this creature")); + // rules fix: workaround to fix "When {this} enters" into "When this xxx enters" + if (EntersBattlefieldTriggeredAbility.ENABLE_TRIGGER_PHRASE_AUTO_FIX) { + if (ability instanceof TriggeredAbility) { + TriggeredAbility triggeredAbility = ((TriggeredAbility) ability); + if (triggeredAbility.getTriggerPhrase() != null && triggeredAbility.getTriggerPhrase().startsWith("When {this} enters")) { + // there are old sets with old oracle, but it's ok for newer sets, so keep that rules fix + // see https://github.com/magefree/mage/issues/12791 + String etbDescription = EntersBattlefieldTriggeredAbility.getThisObjectDescription(this); + triggeredAbility.setTriggerPhrase(triggeredAbility.getTriggerPhrase().replace("{this}", etbDescription)); + } } } - // verify check: all creatures with ETB must use "When this creature enters" instead "When {this} enters" - if (this.isCreature() && ability.getRule().startsWith("When {this} enters")) { - // see above - //throw new IllegalArgumentException("Wrong code usage: creature's ETB ability must use text like \"When this creature enters\""); - } } protected void addAbility(Ability ability, Watcher watcher) {