diff --git a/Mage.Sets/src/mage/cards/b/BallroomBrawlers.java b/Mage.Sets/src/mage/cards/b/BallroomBrawlers.java index 5dbe42a864e..f8122dfd019 100644 --- a/Mage.Sets/src/mage/cards/b/BallroomBrawlers.java +++ b/Mage.Sets/src/mage/cards/b/BallroomBrawlers.java @@ -39,7 +39,7 @@ public final class BallroomBrawlers extends CardImpl { this.toughness = new MageInt(5); // Whenever Ballroom Brawlers attacks, Ballroom Brawlers and up to one other target creature you control each gain your choice of first strike or lifelink until end of turn. - Ability ability = new AttacksTriggeredAbility(new BallroomBrawlersEffect()); + Ability ability = new AttacksTriggeredAbility(new BallroomBrawlersEffect()).setReplaceRuleText(false); ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/Hecatomb.java b/Mage.Sets/src/mage/cards/h/Hecatomb.java index dd50ccda807..4a13b0bdcb0 100644 --- a/Mage.Sets/src/mage/cards/h/Hecatomb.java +++ b/Mage.Sets/src/mage/cards/h/Hecatomb.java @@ -41,7 +41,9 @@ public final class Hecatomb extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}{B}"); // When Hecatomb enters the battlefield, sacrifice Hecatomb unless you sacrifice four creatures. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new SacrificeTargetCost(new TargetControlledPermanent(4, filter2))))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect( + new SacrificeTargetCost(new TargetControlledPermanent(4, filter2)))) + .setReplaceRuleText(false)); // Tap an untapped Swamp you control: Hecatomb deals 1 damage to any target. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapTargetCost(new TargetControlledPermanent(1, 1, filter, true))); diff --git a/Mage.Sets/src/mage/cards/h/HiddenPredators.java b/Mage.Sets/src/mage/cards/h/HiddenPredators.java index 5afe5ffbac8..6a8407a2f35 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenPredators.java +++ b/Mage.Sets/src/mage/cards/h/HiddenPredators.java @@ -47,6 +47,7 @@ class HiddenPredatorsStateTriggeredAbility extends StateTriggeredAbility { public HiddenPredatorsStateTriggeredAbility() { super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new HiddenPredatorsToken(), null, Duration.Custom)); + this.replaceRuleText = false; setTriggerPhrase("When an opponent controls a creature with power 4 or greater, if {this} is an enchantment, "); } diff --git a/Mage.Sets/src/mage/cards/o/OpalAvenger.java b/Mage.Sets/src/mage/cards/o/OpalAvenger.java index b1888072210..d7d79dee934 100644 --- a/Mage.Sets/src/mage/cards/o/OpalAvenger.java +++ b/Mage.Sets/src/mage/cards/o/OpalAvenger.java @@ -41,6 +41,7 @@ class OpalAvengerStateTriggeredAbility extends StateTriggeredAbility { public OpalAvengerStateTriggeredAbility() { super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new OpalAvengerToken(), null, Duration.Custom)); + this.replaceRuleText = false; setTriggerPhrase("When you have 10 or less life, if {this} is an enchantment, "); } diff --git a/Mage.Sets/src/mage/cards/s/SerraInquisitors.java b/Mage.Sets/src/mage/cards/s/SerraInquisitors.java index d5ca8845c00..aec07d592a1 100644 --- a/Mage.Sets/src/mage/cards/s/SerraInquisitors.java +++ b/Mage.Sets/src/mage/cards/s/SerraInquisitors.java @@ -35,7 +35,8 @@ public final class SerraInquisitors extends CardImpl { this.toughness = new MageInt(3); // Whenever Serra Inquisitors blocks or becomes blocked by one or more black creatures, Serra Inquisitors gets +2/+0 until end of turn. - this.addAbility(new BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(new BoostSourceEffect(2, 0, Duration.EndOfTurn), filter, false)); + this.addAbility(new BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(new BoostSourceEffect(2, 0, Duration.EndOfTurn), + filter, false).setReplaceRuleText(false)); } private SerraInquisitors(final SerraInquisitors card) { diff --git a/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java b/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java index 5e516cebb59..4bf21a00734 100644 --- a/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java +++ b/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java @@ -42,6 +42,7 @@ class VeiledCrocodileStateTriggeredAbility extends StateTriggeredAbility { public VeiledCrocodileStateTriggeredAbility() { super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new VeilCrocodileToken(), null, Duration.Custom)); + this.replaceRuleText = false; setTriggerPhrase("When a player has no cards in hand, if {this} is an enchantment, "); } diff --git a/Mage.Sets/src/mage/cards/w/WormfangDrake.java b/Mage.Sets/src/mage/cards/w/WormfangDrake.java index c8130739fd9..71d1e66a8f1 100644 --- a/Mage.Sets/src/mage/cards/w/WormfangDrake.java +++ b/Mage.Sets/src/mage/cards/w/WormfangDrake.java @@ -43,7 +43,7 @@ public final class WormfangDrake extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility( new SacrificeSourceUnlessPaysEffect(new ExileTargetCost(new TargetControlledPermanent(filter))), false - )); + ).setReplaceRuleText(false)); // When Wormfang Drake leaves the battlefield, return the exiled card to the battlefield under its owner's control. this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false)); diff --git a/Mage.Sets/src/mage/cards/y/YuanShaosInfantry.java b/Mage.Sets/src/mage/cards/y/YuanShaosInfantry.java index 5dd56dccef1..de105fd8c97 100644 --- a/Mage.Sets/src/mage/cards/y/YuanShaosInfantry.java +++ b/Mage.Sets/src/mage/cards/y/YuanShaosInfantry.java @@ -28,7 +28,7 @@ public final class YuanShaosInfantry extends CardImpl { // Whenever Yuan Shao's Infantry attacks alone, Yuan Shao's Infantry can't be blocked this combat. Effect effect = new CantBeBlockedSourceEffect(Duration.EndOfCombat); effect.setText("{this} can't be blocked this combat"); - this.addAbility(new AttacksAloneSourceTriggeredAbility(effect)); + this.addAbility(new AttacksAloneSourceTriggeredAbility(effect).setReplaceRuleText(false)); } private YuanShaosInfantry(final YuanShaosInfantry card) { diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbility.java b/Mage/src/main/java/mage/abilities/TriggeredAbility.java index 972a3710e66..430ce33e549 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbility.java @@ -43,6 +43,10 @@ public interface TriggeredAbility extends Ability { TriggeredAbility setTriggersOnceEachTurn(boolean triggersOnce); + TriggeredAbility setDoOnlyOnceEachTurn(boolean doOnlyOnce); + + TriggeredAbility setReplaceRuleText(boolean replaceRuleText); + boolean checkInterveningIfClause(Game game); boolean isOptional(); diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 50c0d4a2a0f..47599564c9b 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -26,8 +26,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge protected boolean leavesTheBattlefieldTrigger; private boolean triggersOnceEachTurn = false; private boolean doOnlyOnceEachTurn = false; + protected boolean replaceRuleText = true; private GameEvent triggerEvent = null; - private String triggerPhrase = null; // TODO: This could be changed to final if all constructors set a value + private String triggerPhrase = null; protected TriggeredAbilityImpl(Zone zone, Effect effect) { this(zone, effect, false); @@ -54,6 +55,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge this.leavesTheBattlefieldTrigger = ability.leavesTheBattlefieldTrigger; this.triggersOnceEachTurn = ability.triggersOnceEachTurn; this.doOnlyOnceEachTurn = ability.doOnlyOnceEachTurn; + this.replaceRuleText = ability.replaceRuleText; this.triggerEvent = ability.triggerEvent; this.triggerPhrase = ability.triggerPhrase; } @@ -103,11 +105,6 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge return lastTurnTriggered == null || lastTurnTriggered != game.getTurnNum(); } - public TriggeredAbility setTriggersOnceEachTurn(boolean triggersOnce) { - this.triggersOnceEachTurn = triggersOnce; - return this; - } - @Override public boolean checkUsedAlready(Game game) { if (!doOnlyOnceEachTurn) { @@ -119,12 +116,25 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge return lastTurnUsed != null && lastTurnUsed == game.getTurnNum(); } + @Override + public TriggeredAbility setTriggersOnceEachTurn(boolean triggersOnce) { + this.triggersOnceEachTurn = triggersOnce; + return this; + } + + @Override public TriggeredAbility setDoOnlyOnceEachTurn(boolean doOnlyOnce) { this.optional = true; this.doOnlyOnceEachTurn = doOnlyOnce; return this; } + @Override + public TriggeredAbility setReplaceRuleText(boolean replaceRuleText) { + this.replaceRuleText = replaceRuleText; + return this; + } + @Override public boolean checkInterveningIfClause(Game game) { return true; @@ -202,41 +212,25 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge } } else if (!ruleLow.startsWith("{this}") && (this.getTargets().isEmpty() - || ruleLow.startsWith("attach") - || ruleLow.startsWith("change") - || ruleLow.startsWith("counter") - || ruleLow.startsWith("destroy") - || ruleLow.startsWith("distribute") - || ruleLow.startsWith("sacrifice") - || ruleLow.startsWith("exchange") - || ruleLow.startsWith("exile") - || ruleLow.startsWith("gain") - || ruleLow.startsWith("goad") - || ruleLow.startsWith("have") - || ruleLow.startsWith("move") - || ruleLow.startsWith("prevent") - || ruleLow.startsWith("put") - || ruleLow.startsWith("remove") - || ruleLow.startsWith("return") - || ruleLow.startsWith("shuffle") - || ruleLow.startsWith("turn") - || ruleLow.startsWith("tap") - || ruleLow.startsWith("untap"))) { + || startsWithVerb(ruleLow))) { sb.append("you may "); } else if (!ruleLow.startsWith("its controller may")) { sb.append("you may have "); - superRule = superRule - .replace(" becomes ", " become ") - .replace(" blocks ", " block ") - .replace(" deals ", " deal ") - .replace(" discards ", " discard ") - .replace(" gains ", " gain ") - .replace(" gets ", " get ") - .replace(" loses ", " lose ") - .replace(" mills ", " mill ") - .replace(" sacrifices ", " sacrifice "); + superRule = ruleWithFixedVerbGrammar(superRule); } - + } + if (replaceRuleText + && triggerPhrase != null + && triggerPhrase.contains("{this}") + && !triggerPhrase.contains("other") + && !triggerPhrase.contains(" of a ") + && !triggerPhrase.contains(" by a ") + && !triggerPhrase.contains(" to a ") + && !triggerPhrase.contains(" blocks a ") + && (superRule.startsWith("{this}") + || superRule.startsWith("sacrifice {this}") + )) { + superRule = superRule.replace("{this} ", "it "); } sb.append(superRule); if (triggersOnceEachTurn) { @@ -246,10 +240,44 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge sb.append(" Do this only once each turn."); } } - return sb.toString(); } + private static boolean startsWithVerb(String ruleLow) { + return ruleLow.startsWith("attach") + || ruleLow.startsWith("change") + || ruleLow.startsWith("counter") + || ruleLow.startsWith("destroy") + || ruleLow.startsWith("distribute") + || ruleLow.startsWith("sacrifice") + || ruleLow.startsWith("exchange") + || ruleLow.startsWith("exile") + || ruleLow.startsWith("gain") + || ruleLow.startsWith("goad") + || ruleLow.startsWith("have") + || ruleLow.startsWith("move") + || ruleLow.startsWith("prevent") + || ruleLow.startsWith("put") + || ruleLow.startsWith("remove") + || ruleLow.startsWith("return") + || ruleLow.startsWith("shuffle") + || ruleLow.startsWith("turn") + || ruleLow.startsWith("tap") + || ruleLow.startsWith("untap"); + } + + private static String ruleWithFixedVerbGrammar(String rule) { + return rule.replace(" becomes ", " become ") + .replace(" blocks ", " block ") + .replace(" deals ", " deal ") + .replace(" discards ", " discard ") + .replace(" gains ", " gain ") + .replace(" gets ", " get ") + .replace(" loses ", " lose ") + .replace(" mills ", " mill ") + .replace(" sacrifices ", " sacrifice "); + } + @Override public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { diff --git a/Mage/src/main/java/mage/abilities/common/BecomesBlockedByCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesBlockedByCreatureTriggeredAbility.java index cd33740e025..d5546145ea8 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesBlockedByCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesBlockedByCreatureTriggeredAbility.java @@ -24,6 +24,7 @@ public class BecomesBlockedByCreatureTriggeredAbility extends TriggeredAbilityIm public BecomesBlockedByCreatureTriggeredAbility(Effect effect, FilterCreaturePermanent filter, boolean optional) { super(Zone.BATTLEFIELD, effect, optional); this.filter = filter; + this.replaceRuleText = false; setTriggerPhrase("Whenever {this} becomes blocked by " + CardUtil.addArticle(filter.getMessage()) + ", "); } diff --git a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java index e6262e807f3..7d28775db0d 100644 --- a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility.java @@ -32,6 +32,7 @@ public class BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility extends Triggered public BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, String rule) { super(Zone.BATTLEFIELD, effect, optional); this.filter = filter; + this.replaceRuleText = false; this.rule = rule; setTriggerPhrase("Whenever {this} blocks or becomes blocked by one or more " + (filter != null ? filter.getMessage() : "creatures") + ", "); } diff --git a/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java b/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java index 61050bd3420..18cadb4c6f9 100644 --- a/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/HeroicAbility.java @@ -34,6 +34,7 @@ public class HeroicAbility extends TriggeredAbilityImpl { if (isHeroic) { this.setAbilityWord(AbilityWord.HEROIC); } + this.replaceRuleText = false; setTriggerPhrase("Whenever you cast a spell that targets {this}, "); } diff --git a/Mage/src/main/java/mage/abilities/keyword/PackTacticsAbility.java b/Mage/src/main/java/mage/abilities/keyword/PackTacticsAbility.java index 1a1c9656821..d942fe0229f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/PackTacticsAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/PackTacticsAbility.java @@ -17,6 +17,7 @@ public class PackTacticsAbility extends TriggeredAbilityImpl { public PackTacticsAbility(Effect effect) { super(Zone.BATTLEFIELD, effect, false); + this.replaceRuleText = false; this.setAbilityWord(AbilityWord.PACK_TACTICS); setTriggerPhrase("Whenever {this} attacks, if you attacked with creatures with total power 6 or greater this combat, "); } diff --git a/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java b/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java index e2ed07278d8..22967dc7d91 100644 --- a/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java @@ -37,6 +37,7 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl { public OrTriggeredAbility(Zone zone, Effect effect, boolean optional, String ruleTrigger, TriggeredAbility... abilities) { super(zone, effect, optional); this.ruleTrigger = ruleTrigger; + this.replaceRuleText = false; Collections.addAll(this.triggeredAbilities, abilities); for (TriggeredAbility ability : triggeredAbilities) { //Remove useless data