rework CombatDamageByToughnessAllEffect (#11180)

new CombatDamageByToughnessControlledEffect
add tests
fix #11179
This commit is contained in:
xenohedron 2023-09-19 01:41:55 -04:00 committed by GitHub
parent 0ad678ff56
commit fa8e93a29d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 172 additions and 43 deletions

View file

@ -2,12 +2,11 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.game.Game;
@ -21,11 +20,10 @@ import java.util.UUID;
public final class AncientLumberknot extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent("each creature you control with toughness greater than its power");
= new FilterCreaturePermanent("creature you control with toughness greater than its power");
static {
filter.add(AncientLumberknotPredicate.instance);
filter.add(TargetController.YOU.getControllerPredicate());
}
public AncientLumberknot(UUID ownerId, CardSetInfo setInfo) {
@ -36,7 +34,7 @@ public final class AncientLumberknot extends CardImpl {
this.toughness = new MageInt(4);
// Each creature you control with toughness greater than its power assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(filter)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect(filter)));
}
private AncientLumberknot(final AncientLumberknot card) {

View file

@ -6,7 +6,7 @@ import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
@ -25,12 +25,10 @@ import java.util.UUID;
public final class ArcadesTheStrategist extends CardImpl {
private static final FilterControlledCreaturePermanent defenderSingle = new FilterControlledCreaturePermanent("a creature with defender");
private static final FilterCreaturePermanent defenderPlural = new FilterCreaturePermanent("Each creature you control with defender");
private static final FilterCreaturePermanent defenderPlural = new FilterCreaturePermanent("creature you control with defender");
static {
defenderSingle.add(new AbilityPredicate(DefenderAbility.class));
defenderPlural.add(TargetController.YOU.getControllerPredicate());
defenderPlural.add(new AbilityPredicate(DefenderAbility.class));
}
@ -55,7 +53,7 @@ public final class ArcadesTheStrategist extends CardImpl {
));
// Each creature you control with defender assigns combat damage equal to its toughness rather than its power and can attack as though it didn't have defender.
Ability ability = new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(defenderPlural));
Ability ability = new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect(defenderPlural));
ability.addEffect(new CanAttackAsThoughItDidntHaveDefenderAllEffect(
Duration.WhileOnBattlefield, defenderSingle
).setText("and can attack as though it didn't have defender"));

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import mage.abilities.Ability;
@ -7,14 +6,13 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderTargetEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.target.common.TargetCreaturePermanent;
@ -36,7 +34,7 @@ public final class AssaultFormation extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
// Each creature you control assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
// {G}: Target creature with defender can attack this turn as though it didn't have defender.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CanAttackAsThoughItDidntHaveDefenderTargetEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{G}"));

View file

@ -16,7 +16,6 @@ import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@ -37,7 +36,7 @@ public final class BaldinCenturyHerdmaster extends CardImpl {
// As long as it's your turn, each creature assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE),
new CombatDamageByToughnessAllEffect(),
MyTurnCondition.instance, "as long as it's your turn, each creature " +
"assigns combat damage equal to its toughness rather than its power"
)));

View file

@ -1,15 +1,13 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
@ -25,7 +23,7 @@ public final class BelligerentBrontodon extends CardImpl {
this.toughness = new MageInt(6);
// Each creature you control assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
}
private BelligerentBrontodon(final BelligerentBrontodon card) {

View file

@ -8,8 +8,6 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import java.util.UUID;
@ -26,8 +24,6 @@ import java.util.UUID;
*/
public final class DoranTheSiegeTower extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("each creature");
public DoranTheSiegeTower(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{B}{G}");
this.supertype.add(SuperType.LEGENDARY);
@ -38,7 +34,7 @@ public final class DoranTheSiegeTower extends CardImpl {
this.toughness = new MageInt(5);
// Each creature assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(filter)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect()));
}
private DoranTheSiegeTower(final DoranTheSiegeTower card) {

View file

@ -6,7 +6,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -27,7 +27,7 @@ public final class HighAlert extends CardImpl {
// Each creature you control assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
// Creatures you control can attack as though they didn't have defender.
this.addAbility(new SimpleStaticAbility(

View file

@ -4,13 +4,12 @@ import mage.abilities.LoyaltyAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import java.util.UUID;
@ -27,7 +26,7 @@ public final class HuatliTheSunsHeart extends CardImpl {
this.setStartingLoyalty(7);
// Each creature you control assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
// -3: You gain life equal to the greatest toughness among creatures you control.
this.addAbility(new LoyaltyAbility(new GainLifeEffect(

View file

@ -9,7 +9,7 @@ import mage.abilities.condition.common.HaveInitiativeCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessAllEffect;
import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -38,7 +38,7 @@ public final class RasaadYnBashir extends CardImpl {
this.toughness = new MageInt(3);
// Each creature you control assigns combat damage equal to its toughness rather than its power.
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE_EACH)));
this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect()));
// Whenever Rasaad yn Bashir attacks, if you have the initiative, double the toughness of each creature you control until end of turn.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(

View file

@ -0,0 +1,84 @@
package org.mage.test.combat;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class CombatDamageByToughnessTest extends CardTestPlayerBase {
@Test
public void testByToughnessAll() {
addCard(Zone.BATTLEFIELD, playerA, "Doran, the Siege Tower", 1); // 0/5
// Each creature assigns combat damage equal to its toughness rather than its power.
addCard(Zone.BATTLEFIELD, playerB, "Kraken Hatchling", 1); // 0/4
attack(1, playerA, "Doran, the Siege Tower");
attack(2, playerB, "Kraken Hatchling");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 4);
assertLife(playerB, 20 - 5);
}
@Test
public void testByToughnessControlled() {
addCard(Zone.BATTLEFIELD, playerA, "Belligerent Brontodon", 1); // 4/6
// Each creature you control assigns combat damage equal to its toughness rather than its power.
addCard(Zone.BATTLEFIELD, playerB, "Maritime Guard", 1); // 1/3
attack(1, playerA, "Belligerent Brontodon");
attack(2, playerB, "Maritime Guard");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20 - 1);
assertLife(playerB, 20 - 6);
}
@Test
public void testByToughnessFilter() {
addCard(Zone.BATTLEFIELD, playerA, "Ancient Lumberknot", 1); // 1/4
// Each creature you control with toughness greater than its power assigns combat damage equal to its toughness rather than its power.
addCard(Zone.BATTLEFIELD, playerA, "Goblin Piker", 1); // 2/1
attack(1, playerA, "Ancient Lumberknot");
attack(1, playerA, "Goblin Piker");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerB, 20 - 4 - 2);
}
@Test
public void testByToughnessTarget() {
addCard(Zone.BATTLEFIELD, playerA, "Walking Bulwark", 1); // 0/3 Defender
// {2}: Until end of turn, target creature with defender gains haste, can attack as though it didn't have defender,
// and assigns combat damage equal to its toughness rather than its power. Activate only as a sorcery.
addCard(Zone.BATTLEFIELD, playerA, "Wild-Field Scarecrow", 1); // 1/4 Defender
addCard(Zone.BATTLEFIELD, playerA, "Wastes", 2);
addCard(Zone.BATTLEFIELD, playerA, "Serra's Blessing", 1); // Creatures you control have vigilance
addCard(Zone.BATTLEFIELD, playerB, "Barony Vampire", 1); // 3/2
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}: Until", "Wild-Field Scarecrow");
attack(1, playerA, "Wild-Field Scarecrow");
attack(2, playerB, "Barony Vampire");
block(2, playerA, "Wild-Field Scarecrow", "Barony Vampire");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerB, 20 - 4);
assertDamageReceived(playerB, "Barony Vampire", 1);
assertDamageReceived(playerA, "Wild-Field Scarecrow", 3);
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common.ruleModifying;
import mage.abilities.Ability;
@ -7,17 +6,25 @@ import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
/**
* @author TheElk801
* @author TheElk801, xanderhall
*/
public class CombatDamageByToughnessAllEffect extends ContinuousEffectImpl {
private final FilterCreaturePermanent filter;
public CombatDamageByToughnessAllEffect() {
this(StaticFilters.FILTER_PERMANENT_CREATURE);
}
/**
* "Each [] assigns combat damage equal to its toughness rather than its power"
* @param filter Warning: ObjectSourcePlayer predicates will be ignored
*/
public CombatDamageByToughnessAllEffect(FilterCreaturePermanent filter) {
this(filter, Duration.WhileOnBattlefield);
}
@ -25,9 +32,8 @@ public class CombatDamageByToughnessAllEffect extends ContinuousEffectImpl {
public CombatDamageByToughnessAllEffect(FilterCreaturePermanent filter, Duration duration) {
super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Neutral);
this.filter = filter;
this.staticText = filter.getMessage() + " assigns combat damage equal to its toughness rather than its power";
this.staticText = "each " + filter.getMessage() + " assigns combat damage equal to its toughness rather than its power";
}
private CombatDamageByToughnessAllEffect(final CombatDamageByToughnessAllEffect effect) {
super(effect);

View file

@ -0,0 +1,59 @@
package mage.abilities.effects.common.ruleModifying;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
/**
* @author TheElk801, xenohedron
*/
public class CombatDamageByToughnessControlledEffect extends ContinuousEffectImpl {
private final FilterCreaturePermanent filter;
public CombatDamageByToughnessControlledEffect() {
this(StaticFilters.FILTER_PERMANENT_CREATURE);
}
/**
* "Each [] you control assigns combat damage equal to its toughness rather than its power"
* @param filter Warning: ObjectSourcePlayer predicates will be ignored
*/
public CombatDamageByToughnessControlledEffect(FilterCreaturePermanent filter) {
this(filter, Duration.WhileOnBattlefield);
}
public CombatDamageByToughnessControlledEffect(FilterCreaturePermanent filter, Duration duration) {
super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Neutral);
this.filter = filter;
this.staticText = "each " + filter.getMessage()
+ (filter.getMessage().contains("you control") ? "" : " you control")
+ " assigns combat damage equal to its toughness rather than its power";
}
private CombatDamageByToughnessControlledEffect(final CombatDamageByToughnessControlledEffect effect) {
super(effect);
this.filter = effect.filter;
}
@Override
public CombatDamageByToughnessControlledEffect copy() {
return new CombatDamageByToughnessControlledEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
FilterCreaturePermanent filterPermanent = filter.copy();
filterPermanent.add(new ControllerIdPredicate(source.getControllerId()));
game.getCombat().setUseToughnessForDamage(true);
game.getCombat().addUseToughnessForDamageFilter(filterPermanent);
return true;
}
}

View file

@ -1229,10 +1229,4 @@ public final class StaticFilters {
FILTER_CONTROLLED_FOOD.setLockedFilter(true);
}
public static final FilterCreaturePermanent FILTER_CONTROLLED_CREATURE_EACH = new FilterCreaturePermanent("each creature you control");
static {
FILTER_CONTROLLED_CREATURE_EACH.add(TargetController.YOU.getPlayerPredicate());
FILTER_CONTROLLED_CREATURE_EACH.setLockedFilter(true);
}
}