Rework affinity implementation (#13707)

* rework affinity implementation

* move filters
This commit is contained in:
Evan Kranzler 2025-05-31 22:00:13 -04:00 committed by GitHub
parent bca7fb8ccb
commit db193bd499
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 310 additions and 466 deletions

View file

@ -1,18 +1,13 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import java.util.UUID;
@ -21,9 +16,6 @@ import java.util.UUID;
*/
public final class AngelicObserver extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.CITIZEN, "Citizens");
private static final Hint hint = new ValueHint("Citizens you control", new PermanentsOnBattlefieldCount(filter));
public AngelicObserver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}");
@ -32,8 +24,8 @@ public final class AngelicObserver extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// This spell costs {1} less to cast for each Citizen you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).setRuleAtTheTop(true).addHint(hint));
// Affinity for Citizens
this.addAbility(new AffinityAbility(AffinityType.CITIZENS));
// Flying
this.addAbility(FlyingAbility.getInstance());

View file

@ -5,7 +5,7 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.abilities.hint.common.GatesYouControlHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -39,7 +39,7 @@ public final class ArchwayAngel extends CardImpl {
// When Archway Angel enters the battlefield, you gain 2 life for each Gate you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(new PermanentsOnBattlefieldCount(filter, 2)));
ability.addHint(GateYouControlHint.instance);
ability.addHint(GatesYouControlHint.instance);
this.addAbility(ability);
}

View file

@ -1,17 +1,13 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.common.CreaturesYouControlHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import java.util.UUID;
@ -20,8 +16,6 @@ import java.util.UUID;
*/
public final class ArgivianPhalanx extends CardImpl {
static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("creatures");
public ArgivianPhalanx(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}");
@ -31,8 +25,8 @@ public final class ArgivianPhalanx extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// This spell costs {1} less to cast for each creature you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(CreaturesYouControlHint.instance));
// Affinity for creatures
this.addAbility(new AffinityAbility(AffinityType.CREATURES));
// Vigilance
this.addAbility(VigilanceAbility.getInstance());

View file

@ -2,19 +2,13 @@ package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.HistoricPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -24,19 +18,11 @@ import java.util.UUID;
*/
public final class BanishToAnotherUniverse extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("historic permanents");
private static final Hint hint = new ValueHint("historic permanents you control", new PermanentsOnBattlefieldCount(filter));
static {
filter.add(HistoricPredicate.instance);
}
public BanishToAnotherUniverse(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}");
// Affinity for historic permanents
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter))
.addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.HISTORIC));
// When Banish to Another Universe enters the battlefield, exile target nonland permanent an opponent controls until Banish to Another Universe leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());

View file

@ -4,26 +4,21 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.IndestructibleAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
@ -32,8 +27,6 @@ import java.util.UUID;
*/
public final class BanquetGuests extends CardImpl {
private static final Hint hint = new ValueHint("Food you control", new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_FOOD));
public BanquetGuests(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{G}{W}");
@ -43,12 +36,7 @@ public final class BanquetGuests extends CardImpl {
this.toughness = new MageInt(0);
// Affinity for Food
this.addAbility(
new SimpleStaticAbility(
Zone.ALL,
new AffinityEffect(StaticFilters.FILTER_CONTROLLED_FOOD)
).addHint(hint)
);
this.addAbility(new AffinityAbility(AffinityType.FOOD));
// Trample
this.addAbility(TrampleAbility.getInstance());

View file

@ -3,12 +3,8 @@ package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@ -26,9 +22,6 @@ import java.util.UUID;
*/
public final class BartzAndBoko extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.BIRD, "Birds");
private static final Hint hint = new ValueHint("Birds you control", new PermanentsOnBattlefieldCount(filter));
public BartzAndBoko(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
@ -39,7 +32,7 @@ public final class BartzAndBoko extends CardImpl {
this.toughness = new MageInt(3);
// Affinity for Birds
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).setRuleAtTheTop(true).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.BIRDS));
// When Bartz and Boko enters, each other Bird you control deals damage equal to its power to target creature an opponent controls.
Ability ability = new EntersBattlefieldTriggeredAbility(new BartzAndBokoEffect());

View file

@ -1,18 +1,12 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledEnchantmentPermanent;
import mage.filter.common.FilterControlledPermanent;
import java.util.UUID;
@ -21,9 +15,6 @@ import java.util.UUID;
*/
public final class BrineGiant extends CardImpl {
static final FilterControlledPermanent filter = new FilterControlledEnchantmentPermanent("enchantments");
private static final Hint hint = new ValueHint("Enchantments you control", new PermanentsOnBattlefieldCount(filter));
public BrineGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}");
@ -31,8 +22,8 @@ public final class BrineGiant extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(6);
// This spell costs {1} less to cast for each enchantment you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
// Affinity for enchantments
this.addAbility(new AffinityAbility(AffinityType.ENCHANTMENTS));
}
private BrineGiant(final BrineGiant card) {

View file

@ -1,30 +1,30 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.AffinityForLandTypeAbility;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.FearAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class DrossGolem extends CardImpl {
public DrossGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Affinity for Swamps
this.addAbility(new AffinityForLandTypeAbility(SubType.SWAMP, "Swamps"));
this.addAbility(new AffinityAbility(AffinityType.SWAMPS));
// Fear
this.addAbility(FearAbility.getInstance());
}

View file

@ -2,13 +2,12 @@ package mage.cards.g;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.PutOnLibrarySourceEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.DauntAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
@ -21,8 +20,7 @@ import java.util.UUID;
*/
public final class GateColossus extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.GATE, "Gates");
private static final FilterControlledPermanent filter2 = new FilterControlledPermanent(SubType.GATE);
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.GATE);
public GateColossus(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{8}");
@ -31,8 +29,8 @@ public final class GateColossus extends CardImpl {
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// This spell costs {1} less to cast for each Gate you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(GateYouControlHint.instance));
// Affinity for Gates
this.addAbility(new AffinityAbility(AffinityType.GATES));
// Gate Colossus can't be blocked by creatures with power 2 or less.
this.addAbility(new DauntAbility());
@ -42,7 +40,7 @@ public final class GateColossus extends CardImpl {
Zone.GRAVEYARD,
new PutOnLibrarySourceEffect(
true, "put this card from your graveyard on top of your library"
), filter2, true
), filter, true
));
}

View file

@ -10,7 +10,7 @@ import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.abilities.hint.common.GatesYouControlHint;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
@ -51,7 +51,7 @@ public final class GatebreakerRam extends CardImpl {
this.addAbility(new SimpleStaticAbility(
new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield)
.setText("{this} gets +1/+1 for each Gate you control.")
).addHint(GateYouControlHint.instance));
).addHint(GatesYouControlHint.instance));
// As long as you control two or more Gates, Gatebreaker Ram has vigilance and trample.
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(

View file

@ -4,7 +4,7 @@ import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.common.GateYouControlCount;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.abilities.hint.common.GatesYouControlHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -35,7 +35,7 @@ public final class GatekeeperGargoyle extends CardImpl {
CounterType.P1P1.createInstance(),
GateYouControlCount.instance, true
), "with a +1/+1 counter on it for each Gate you control"
).addHint(GateYouControlHint.instance));
).addHint(GatesYouControlHint.instance));
}
private GatekeeperGargoyle(final GatekeeperGargoyle card) {

View file

@ -6,7 +6,7 @@ import mage.abilities.dynamicvalue.common.GateYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.abilities.hint.common.GatesYouControlHint;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.abilities.keyword.VigilanceAbility;
@ -36,7 +36,7 @@ public final class GlaiveOfTheGuildpact extends CardImpl {
ability.addEffect(new GainAbilityAttachedEffect(
new MenaceAbility(), AttachmentType.EQUIPMENT
).setText("and menace. <i>(A creature with menace can't be blocked except by two or more creatures.)</i>"));
ability.addHint(GateYouControlHint.instance);
ability.addHint(GatesYouControlHint.instance);
this.addAbility(ability);
// Equip {3}

View file

@ -1,18 +1,17 @@
package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledPermanent;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.RebelRedToken;
@ -28,18 +27,11 @@ import java.util.UUID;
*/
public final class GoldwardensGambit extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledPermanent(SubType.EQUIPMENT, "Equipment");
private static final Hint hint = new ValueHint(
"Equipment you control", new PermanentsOnBattlefieldCount(filter)
);
public GoldwardensGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{R}{R}");
// Affinity for Equipment
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.EQUIPMENT));
// Create five 2/2 red Rebel creature tokens. They gain haste until end of turn. For each of those tokens, you may attach an Equipment you control to it.
this.getSpellAbility().addEffect(new GoldwardensGambitEffect());
@ -53,10 +45,6 @@ public final class GoldwardensGambit extends CardImpl {
public GoldwardensGambit copy() {
return new GoldwardensGambit(this);
}
public static FilterControlledPermanent getFilter() {
return filter;
}
}
class GoldwardensGambitEffect extends OneShotEffect {
@ -87,7 +75,7 @@ class GoldwardensGambitEffect extends OneShotEffect {
game.addEffect(new GainAbilityTargetEffect(
HasteAbility.getInstance(), Duration.EndOfTurn
).setTargetPointer(new FixedTargets(token, game)), source);
if (game.getBattlefield().count(GoldwardensGambit.getFilter(), source.getControllerId(), source, game) < 1) {
if (game.getBattlefield().count(StaticFilters.FILTER_CONTROLLED_PERMANENT_EQUIPMENT, source.getControllerId(), source, game) < 1) {
return true;
}
for (UUID tokenId : token.getLastAddedTokenIds()) {
@ -98,7 +86,7 @@ class GoldwardensGambitEffect extends OneShotEffect {
)) {
continue;
}
TargetPermanent target = new TargetPermanent(0, 1, GoldwardensGambit.getFilter(), true);
TargetPermanent target = new TargetPermanent(0, 1, StaticFilters.FILTER_CONTROLLED_PERMANENT_EQUIPMENT, true);
player.choose(Outcome.BoostCreature, target, source, game);
permanent.addAttachment(target.getFirstTarget(), source, game);
}

View file

@ -1,19 +1,13 @@
package mage.cards.h;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.OutlawPredicate;
import java.util.UUID;
@ -22,16 +16,6 @@ import java.util.UUID;
*/
public final class HellspurBrute extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("outlaws");
static {
filter.add(OutlawPredicate.instance);
}
private static final Hint hint = new ValueHint(
"Outlaws you control", new PermanentsOnBattlefieldCount(filter)
);
public HellspurBrute(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
@ -41,7 +25,7 @@ public final class HellspurBrute extends CardImpl {
this.toughness = new MageInt(4);
// Affinity for outlaws
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.OUTLAWS));
// Trample
this.addAbility(TrampleAbility.getInstance());

View file

@ -6,13 +6,12 @@ import mage.abilities.dynamicvalue.common.GateYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.abilities.hint.common.GatesYouControlHint;
import mage.abilities.keyword.VigilanceAbility;
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 java.util.UUID;
@ -33,7 +32,7 @@ public final class HoldTheGates extends CardImpl {
new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED)
.setText("and have vigilance")
);
ability.addHint(GateYouControlHint.instance);
ability.addHint(GatesYouControlHint.instance);
this.addAbility(ability);
}

View file

@ -4,22 +4,18 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DontUntapInPlayersNextUntapStepAllEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.common.FilterControlledPermanent;
@ -39,8 +35,6 @@ public final class IcebreakerKraken extends CardImpl {
filter.add(SuperType.SNOW.getPredicate());
}
private static final Hint hint = new ValueHint("Snow lands you control", new PermanentsOnBattlefieldCount(filter));
public IcebreakerKraken(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{10}{U}{U}");
@ -49,8 +43,8 @@ public final class IcebreakerKraken extends CardImpl {
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// This spell costs {1} less to cast for each snow land you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
// Affinity for snow lands
this.addAbility(new AffinityAbility(AffinityType.SNOW_LANDS));
// When Icebreaker Kraken enters the battlefield, artifacts and creatures target opponent controls don't untap during that player's next untap step.
Effect effect = new DontUntapInPlayersNextUntapStepAllEffect(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE);

View file

@ -3,24 +3,15 @@ package mage.cards.j;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -30,16 +21,6 @@ import java.util.UUID;
*/
public final class JunkWinder extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("tokens");
private static final FilterPermanent filter2 = new FilterNonlandPermanent("nonland permanent an opponent controls");
static {
filter.add(TokenPredicate.TRUE);
filter2.add(TargetController.OPPONENT.getControllerPredicate());
}
private static final Hint hint = new ValueHint("Tokens you control", new PermanentsOnBattlefieldCount(filter));
public JunkWinder(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
@ -48,7 +29,7 @@ public final class JunkWinder extends CardImpl {
this.toughness = new MageInt(6);
// Affinity for tokens
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.TOKENS));
// Whenever a token you control enters, tap target nonland permanent an opponent controls. It doesn't untap during its controller's next untap step.
Ability ability = new EntersBattlefieldControlledTriggeredAbility(

View file

@ -3,19 +3,12 @@ package mage.cards.m;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.TokenPredicate;
@ -33,9 +26,6 @@ import java.util.UUID;
*/
public final class MillicentRestlessRevenant extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.SPIRIT, "Spirits");
private static final Hint hint = new ValueHint("Spirits you control", new PermanentsOnBattlefieldCount(filter));
public MillicentRestlessRevenant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}{U}");
@ -45,8 +35,8 @@ public final class MillicentRestlessRevenant extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// This spell costs {1} less to cast for each Spirit you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
// Affinity for Spirits
this.addAbility(new AffinityAbility(AffinityType.SPIRITS));
// Flying
this.addAbility(FlyingAbility.getInstance());

View file

@ -3,20 +3,14 @@ package mage.cards.n;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.EquippedPredicate;
import mage.game.Game;
import mage.players.Player;
@ -26,19 +20,12 @@ import java.util.UUID;
* @author correl
*/
public final class NahiriForgedInFury extends CardImpl {
private static final FilterControlledPermanent equipmentFilter = new FilterControlledPermanent(SubType.EQUIPMENT,
"Equipment");
private static final FilterControlledCreaturePermanent equippedFilter = new FilterControlledCreaturePermanent(
"an equipped creature you control");
private static final Hint hint = new ValueHint(
"Equipment you control", new PermanentsOnBattlefieldCount(equipmentFilter));
static {
equippedFilter.add(EquippedPredicate.instance);
}
public NahiriForgedInFury(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{4}{R}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.KOR);
@ -47,7 +34,8 @@ public final class NahiriForgedInFury extends CardImpl {
this.toughness = new MageInt(4);
// Affinity for Equipment
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(equipmentFilter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.EQUIPMENT));
// Whenever an equipped creature you control attacks, exile the top card
// of your library. You may play that card this turn. You may cast
// Equipment spells this way without paying their mana costs.

View file

@ -1,32 +1,21 @@
package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.constants.SubType;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class OxiddaFinisher extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledPermanent(SubType.EQUIPMENT, "Equipment");
private static final Hint hint = new ValueHint(
"Equipment you control", new PermanentsOnBattlefieldCount(filter)
);
public OxiddaFinisher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
@ -36,7 +25,7 @@ public final class OxiddaFinisher extends CardImpl {
this.toughness = new MageInt(5);
// Affinity for Equipment
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.EQUIPMENT));
// Trample
this.addAbility(TrampleAbility.getInstance());

View file

@ -1,30 +1,30 @@
package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.AffinityForLandTypeAbility;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class OxiddaGolem extends CardImpl {
public OxiddaGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{6}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Affinity for Mountains
this.addAbility(new AffinityForLandTypeAbility(SubType.MOUNTAIN, "Mountains"));
this.addAbility(new AffinityAbility(AffinityType.MOUNTAINS));
// Haste
this.addAbility(HasteAbility.getInstance());
}

View file

@ -3,19 +3,16 @@ package mage.cards.p;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledPermanent;
@ -37,11 +34,6 @@ public final class PearlEarImperialAdvisor extends CardImpl {
filter.add(CardType.ENCHANTMENT.getPredicate());
}
private static final FilterControlledPermanent filterPermanentAura = new FilterControlledPermanent(SubType.AURA, "Auras");
private static final Hint hint = new ValueHint(
"Auras you control", new PermanentsOnBattlefieldCount(filterPermanentAura)
);
private static final FilterPermanent filterModified = new FilterControlledPermanent();
private static final FilterSpell filterAura = new FilterSpell("an Aura spell that targets a modified permanent you control");
@ -64,12 +56,7 @@ public final class PearlEarImperialAdvisor extends CardImpl {
this.addAbility(LifelinkAbility.getInstance());
// Enchantment spells you cast have affinity for Auras.
this.addAbility(new SimpleStaticAbility(
new GainAbilityControlledSpellsEffect(
new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filterPermanentAura)).addHint(hint),
filter
)
));
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledSpellsEffect(new AffinityAbility(AffinityType.AURAS), filter)));
// Whenever you cast an Aura spell that targets a modified permanent you control, draw a card.
this.addAbility(new SpellCastControllerTriggeredAbility(new DrawCardSourceControllerEffect(1), filterAura, false));

View file

@ -1,18 +1,12 @@
package mage.cards.p;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
@ -23,14 +17,11 @@ import java.util.UUID;
*/
public final class Polliwallop extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.FROG, "Frogs");
private static final Hint hint = new ValueHint("Frogs you control", new PermanentsOnBattlefieldCount(filter));
public Polliwallop(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}");
// This spell costs {1} less to cast for each Frog you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).setRuleAtTheTop(true).addHint(hint));
// Affinity for Frogs
this.addAbility(new AffinityAbility(AffinityType.FROGS));
// Target creature you control deals damage equal to twice its power to target creature you don't control.
this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("", 2));

View file

@ -1,30 +1,29 @@
package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.AffinityForLandTypeAbility;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class RazorGolem extends CardImpl {
public RazorGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{6}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// Affinity for Plains
this.addAbility(new AffinityForLandTypeAbility(SubType.PLAINS, "Plains"));
this.addAbility(new AffinityAbility(AffinityType.PLAINS));
// Vigilance
this.addAbility(VigilanceAbility.getInstance());

View file

@ -1,20 +1,14 @@
package mage.cards.r;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetCreatureOrPlaneswalker;
import java.util.UUID;
@ -24,18 +18,11 @@ import java.util.UUID;
*/
public final class RebelSalvo extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledPermanent(SubType.EQUIPMENT, "Equipment");
private static final Hint hint = new ValueHint(
"Equipment you control", new PermanentsOnBattlefieldCount(filter)
);
public RebelSalvo(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
// Affinity for Equipment
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.EQUIPMENT));
// Rebel Salvo deals 5 damage to target creature or planeswalker. That permanent loses indestructible until end of turn.
this.getSpellAbility().addEffect(new DamageTargetEffect(5));

View file

@ -2,24 +2,16 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.AttackedThisTurnSourceCondition;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.HumanSoldierToken;
@ -32,9 +24,6 @@ import java.util.UUID;
*/
public final class RidersOfTheMark extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.HUMAN, "Humans");
private static final Hint hint = new ValueHint("Humans you control", new PermanentsOnBattlefieldCount(filter));
public RidersOfTheMark(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{R}");
@ -43,8 +32,8 @@ public final class RidersOfTheMark extends CardImpl {
this.power = new MageInt(7);
this.toughness = new MageInt(4);
// This spell costs {1} less to cast for each Human you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).setRuleAtTheTop(true).addHint(hint));
// Affinity for Humans
this.addAbility(new AffinityAbility(AffinityType.HUMANS));
// Trample
this.addAbility(TrampleAbility.getInstance());

View file

@ -1,21 +1,15 @@
package mage.cards.s;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.IndestructibleAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@ -25,14 +19,11 @@ import java.util.UUID;
*/
public final class ScalesOfShale extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.LIZARD, "Lizards");
private static final Hint hint = new ValueHint("Lizards you control", new PermanentsOnBattlefieldCount(filter));
public ScalesOfShale(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}");
// This spell costs {1} less to cast for each Lizard you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).setRuleAtTheTop(true).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.LIZARDS));
// Target creature gets +2/+0 and gains lifelink and indestructible until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(

View file

@ -1,19 +1,13 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledEnchantmentPermanent;
import mage.filter.common.FilterControlledPermanent;
import java.util.UUID;
@ -22,9 +16,6 @@ import java.util.UUID;
*/
public final class SkyBlessedSamurai extends CardImpl {
static final FilterControlledPermanent filter = new FilterControlledEnchantmentPermanent("enchantments");
private static final Hint hint = new ValueHint("Enchantments you control", new PermanentsOnBattlefieldCount(filter));
public SkyBlessedSamurai(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{6}{W}");
@ -33,8 +24,8 @@ public final class SkyBlessedSamurai extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// This spell costs {1} less to cast for each enchantment you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
// Affinity for enchantments
this.addAbility(new AffinityAbility(AffinityType.ENCHANTMENTS));
// Flying
this.addAbility(FlyingAbility.getInstance());

View file

@ -1,30 +1,30 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.AffinityForLandTypeAbility;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class SpireGolem extends CardImpl {
public SpireGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{6}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(2);
this.toughness = new MageInt(4);
// Affinity for Islands
this.addAbility(new AffinityForLandTypeAbility(SubType.ISLAND, "Islands"));
this.addAbility(new AffinityAbility(AffinityType.ISLANDS));
// Flying
this.addAbility(FlyingAbility.getInstance());
}

View file

@ -1,28 +1,28 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.keyword.AffinityForLandTypeAbility;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class TangleGolem extends CardImpl {
public TangleGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}");
this.subtype.add(SubType.GOLEM);
this.power = new MageInt(5);
this.toughness = new MageInt(4);
// Affinity for Forests
this.addAbility(new AffinityForLandTypeAbility(SubType.FOREST, "Forests"));
this.addAbility(new AffinityAbility(AffinityType.FORESTS));
}
private TangleGolem(final TangleGolem card) {

View file

@ -6,17 +6,16 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledPermanent;
import mage.game.permanent.token.KnightToken;
import java.util.UUID;
@ -26,22 +25,19 @@ import java.util.UUID;
*/
public final class TheCircleOfLoyalty extends CardImpl {
private static final FilterControlledPermanent filterKnight = new FilterControlledPermanent(SubType.KNIGHT, "Knights");
private static final FilterSpell filterLegendary = new FilterSpell("a legendary spell");
static {
filterLegendary.add(SuperType.LEGENDARY.getPredicate());
}
private static final Hint hint = new ValueHint("Knights you control", new PermanentsOnBattlefieldCount(filterKnight));
public TheCircleOfLoyalty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}{W}{W}");
this.supertype.add(SuperType.LEGENDARY);
// This spell costs {1} less to cast for each Knight you control.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filterKnight)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.KNIGHTS));
// Creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(

View file

@ -3,12 +3,9 @@ package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.FaceVillainousChoiceOpponentsEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
import mage.cards.CardImpl;
@ -32,7 +29,6 @@ import java.util.UUID;
public final class TheDalekEmperor extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.DALEK, "Daleks");
private static final Hint hint = new ValueHint("Daleks you control", new PermanentsOnBattlefieldCount(filter));
private static final FaceVillainousChoice choice = new FaceVillainousChoice(
Outcome.Sacrifice, new TheDalekEmperorFirstChoice(), new TheDalekEmperorSecondChoice()
);
@ -46,7 +42,7 @@ public final class TheDalekEmperor extends CardImpl {
this.toughness = new MageInt(6);
// Affinity for Daleks
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.DALEKS));
// Other Daleks you control have haste.
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(

View file

@ -1,39 +1,27 @@
package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterControlledPlaneswalkerPermanent;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author DominionSpy
*/
public final class TomikWielderOfLaw extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPlaneswalkerPermanent("planeswalkers");
private static final Hint hint = new ValueHint("planeswalkers you control", new PermanentsOnBattlefieldCount(filter));
public TomikWielderOfLaw(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}");
@ -44,8 +32,7 @@ public final class TomikWielderOfLaw extends CardImpl {
this.toughness = new MageInt(4);
// Affinity for planeswalkers
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter))
.addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.PLANESWALKERS));
// Flying
this.addAbility(FlyingAbility.getInstance());

View file

@ -1,17 +1,11 @@
package mage.cards.t;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AffinityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import java.util.UUID;
@ -20,14 +14,11 @@ import java.util.UUID;
*/
public final class TravelTheOverworld extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.TOWN, "Towns");
private static final Hint hint = new ValueHint("Towns you control", new PermanentsOnBattlefieldCount(filter));
public TravelTheOverworld(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{U}{U}");
// Affinity for Towns
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).setRuleAtTheTop(true).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.TOWNS));
// Draw four cards.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4));

View file

@ -1,15 +1,12 @@
package mage.cards.u;
import mage.MageInt;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.AffinityAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@ -27,14 +24,6 @@ public final class UrzaChiefArtificer extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledCreaturePermanent("artifact creatures");
static {
filter.add(CardType.ARTIFACT.getPredicate());
}
private static final Hint hint = new ValueHint(
"Artifact creatures you control", new PermanentsOnBattlefieldCount(filter)
);
public UrzaChiefArtificer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{U}{B}");
@ -45,7 +34,7 @@ public final class UrzaChiefArtificer extends CardImpl {
this.toughness = new MageInt(5);
// Affinity for artifact creatures
this.addAbility(new SimpleStaticAbility(Zone.ALL, new AffinityEffect(filter)).addHint(hint));
this.addAbility(new AffinityAbility(AffinityType.ARTIFACT_CREATURES));
// Artifact creatures you control have menace.
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
@ -53,9 +42,7 @@ public final class UrzaChiefArtificer extends CardImpl {
));
// At the beginning of your end step, create a 0/0 colorless Construct artifact creature token with "This creature gets +1/+1 for each artifact you control."
this.addAbility(new BeginningOfEndStepTriggeredAbility(
new CreateTokenEffect(new KarnConstructToken())
));
this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new KarnConstructToken())));
}
private UrzaChiefArtificer(final UrzaChiefArtificer card) {

View file

@ -9,11 +9,11 @@ import mage.game.Game;
/**
* @author JayDi85
*/
public enum GateYouControlHint implements Hint {
public enum GatesYouControlHint implements Hint {
instance;
private static final Hint hint = new ValueHint("Gate you control", GateYouControlCount.instance);
private static final Hint hint = new ValueHint("Gates you control", GateYouControlCount.instance);
@Override
public String getText(Game game, Ability ability) {

View file

@ -1,11 +1,10 @@
package mage.abilities.effects.common;
package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.constants.CostModificationType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.*;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.util.CardUtil;
@ -15,15 +14,45 @@ import mage.util.CardUtil;
* 702.40a Affinity is a static ability that functions while the spell with affinity is on the stack.
* Affinity for [text] means This spell costs you {1} less to cast for each [text] you control.
* 702.40b If a spell has multiple instances of affinity, each of them applies.
*
* @author Loki, TheElk801
*/
public class AffinityEffect extends CostModificationEffectImpl {
public class AffinityAbility extends SimpleStaticAbility {
private AffinityType affinityType;
public AffinityAbility(AffinityType affinityType) {
super(Zone.ALL, new AffinityEffect(affinityType.getFilter()));
setRuleAtTheTop(true);
this.addHint(affinityType.getHint());
this.affinityType = affinityType;
}
protected AffinityAbility(final AffinityAbility ability) {
super(ability);
this.affinityType = ability.affinityType;
}
@Override
public AffinityAbility copy() {
return new AffinityAbility(this);
}
@Override
public String getRule() {
return "Affinity for " + affinityType.getFilter().getMessage() +
" <i>(This spell costs {1} less to cast for each " +
affinityType.getSingularName() + " you control.)</i>";
}
}
class AffinityEffect extends CostModificationEffectImpl {
private final FilterControlledPermanent filter;
public AffinityEffect(FilterControlledPermanent affinityFilter) {
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = affinityFilter;
staticText = "Affinity for " + filter.getMessage();
}
protected AffinityEffect(final AffinityEffect effect) {
@ -34,14 +63,18 @@ public class AffinityEffect extends CostModificationEffectImpl {
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
// abilityToModify.getControllerId() works with Sen Triplets and in multiplayer games, see https://github.com/magefree/mage/issues/5931
int count = game.getBattlefield().getActivePermanents(filter, abilityToModify.getControllerId(), source, game).size();
CardUtil.reduceCost(abilityToModify, count);
CardUtil.reduceCost(
abilityToModify, game.getBattlefield().count(
filter, abilityToModify.getControllerId(), source, game
)
);
return true;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
return abilityToModify instanceof SpellAbility && abilityToModify.getSourceId().equals(source.getSourceId());
return abilityToModify instanceof SpellAbility
&& abilityToModify.getSourceId().equals(source.getSourceId());
}
@Override

View file

@ -1,21 +1,14 @@
package mage.abilities.keyword;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.constants.AffinityType;
/**
* Affinity for artifacts
*/
public class AffinityForArtifactsAbility extends SimpleStaticAbility {
public class AffinityForArtifactsAbility extends AffinityAbility {
public AffinityForArtifactsAbility() {
super(Zone.ALL, new AffinityEffect(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT));
setRuleAtTheTop(true);
this.addHint(ArtifactYouControlHint.instance);
super(AffinityType.ARTIFACTS);
}
protected AffinityForArtifactsAbility(final AffinityForArtifactsAbility ability) {
@ -26,9 +19,4 @@ public class AffinityForArtifactsAbility extends SimpleStaticAbility {
public AffinityForArtifactsAbility copy() {
return new AffinityForArtifactsAbility(this);
}
@Override
public String getRule() {
return "Affinity for artifacts <i>(This spell costs {1} less to cast for each artifact you control.)</i>";
}
}

View file

@ -1,42 +0,0 @@
package mage.abilities.keyword;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AffinityEffect;
import mage.abilities.hint.ValueHint;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
/**
* @author LevelX2
*/
public class AffinityForLandTypeAbility extends SimpleStaticAbility {
private final String rulesText;
public AffinityForLandTypeAbility(SubType landType, String pluralName) {
super(Zone.ALL, null);
rulesText = "Affinity for " + pluralName + " <i>(This spell costs {1} less to cast for each " + landType + " you control.)</i>";
setRuleAtTheTop(true);
FilterControlledPermanent filter = new FilterControlledPermanent(landType);
addEffect(new AffinityEffect(filter));
addHint(new ValueHint(pluralName + " you control", new PermanentsOnBattlefieldCount(filter)));
}
protected AffinityForLandTypeAbility(final AffinityForLandTypeAbility ability) {
super(ability);
this.rulesText = ability.rulesText;
}
@Override
public AffinityForLandTypeAbility copy() {
return new AffinityForLandTypeAbility(this);
}
@Override
public String getRule() {
return rulesText;
}
}

View file

@ -0,0 +1,119 @@
package mage.constants;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.abilities.hint.common.CreaturesYouControlHint;
import mage.abilities.hint.common.GatesYouControlHint;
import mage.filter.common.*;
import mage.filter.predicate.mageobject.HistoricPredicate;
import mage.filter.predicate.mageobject.OutlawPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.util.CardUtil;
/**
* @author TheElk801
*/
public enum AffinityType {
ARTIFACTS(new FilterControlledArtifactPermanent("artifacts"), ArtifactYouControlHint.instance),
CREATURES(new FilterControlledCreaturePermanent("creatures"), CreaturesYouControlHint.instance),
ARTIFACT_CREATURES(AffinityFilters.ARTIFACT_CREATURES),
ENCHANTMENTS(new FilterControlledEnchantmentPermanent("enchantments")),
PLANESWALKERS(new FilterControlledPlaneswalkerPermanent("planeswalker")),
EQUIPMENT(new FilterControlledPermanent(SubType.EQUIPMENT, "Equipment"), "Equipment"),
AURAS(new FilterControlledPermanent(SubType.AURA, "Auras")),
FOOD(new FilterControlledPermanent(SubType.FOOD, "Food"), "Food"),
TOKENS(AffinityFilters.TOKENS),
PLAINS(new FilterControlledPermanent(SubType.PLAINS, "Plains")),
ISLANDS(new FilterControlledPermanent(SubType.ISLAND, "Islands")),
SWAMPS(new FilterControlledPermanent(SubType.SWAMP, "Swamps")),
MOUNTAINS(new FilterControlledPermanent(SubType.MOUNTAIN, "Mountains")),
FORESTS(new FilterControlledPermanent(SubType.FOREST, "Forests")),
SPIRITS(new FilterControlledPermanent(SubType.SPIRIT, "Spirits")),
HUMANS(new FilterControlledPermanent(SubType.HUMAN, "Humans")),
KNIGHTS(new FilterControlledPermanent(SubType.KNIGHT, "Knights")),
DALEKS(new FilterControlledPermanent(SubType.DALEK, "Daleks")),
FROGS(new FilterControlledPermanent(SubType.FROG, "Frogs")),
LIZARDS(new FilterControlledPermanent(SubType.LIZARD, "Lizards")),
BIRDS(new FilterControlledPermanent(SubType.BIRD, "Birds")),
CITIZENS(new FilterControlledPermanent(SubType.CITIZEN, "Citizens")),
TOWNS(new FilterControlledPermanent(SubType.TOWN, "Towns")),
GATES(new FilterControlledPermanent(SubType.GATE, "Gates"), GatesYouControlHint.instance),
SNOW_LANDS(AffinityFilters.SNOW_LANDS),
HISTORIC(AffinityFilters.HISTORIC),
OUTLAWS(AffinityFilters.OUTLAWS);
private final FilterControlledPermanent filter;
private final Hint hint;
private final String singularName;
AffinityType(FilterControlledPermanent filter) {
this(filter, filter.getMessage());
}
AffinityType(FilterControlledPermanent filter, String singularName) {
this(filter, new ValueHint(
CardUtil.getTextWithFirstCharUpperCase(filter.getMessage()) + " you control",
new PermanentsOnBattlefieldCount(filter)
), singularName);
}
AffinityType(FilterControlledPermanent filter, Hint hint) {
this(filter, hint, filter.getMessage().substring(0, filter.getMessage().length() - 1));
}
AffinityType(FilterControlledPermanent filter, Hint hint, String singularName) {
this.filter = filter;
this.hint = hint;
this.singularName = singularName;
}
public FilterControlledPermanent getFilter() {
return filter;
}
public Hint getHint() {
return hint;
}
public String getSingularName() {
return singularName;
}
}
class AffinityFilters {
public static final FilterControlledPermanent TOKENS = new FilterControlledPermanent("tokens");
static {
TOKENS.add(TokenPredicate.TRUE);
}
public static final FilterControlledPermanent SNOW_LANDS = new FilterControlledLandPermanent("snow lands");
static {
SNOW_LANDS.add(SuperType.SNOW.getPredicate());
}
public static final FilterControlledPermanent OUTLAWS = new FilterControlledPermanent("outlaws");
static {
OUTLAWS.add(OutlawPredicate.instance);
}
public static final FilterControlledPermanent HISTORIC = new FilterControlledPermanent("historic permanents");
static {
HISTORIC.add(HistoricPredicate.instance);
}
public static final FilterControlledPermanent ARTIFACT_CREATURES = new FilterControlledPermanent("artifact creatures");
static {
ARTIFACT_CREATURES.add(CardType.ARTIFACT.getPredicate());
ARTIFACT_CREATURES.add(CardType.CREATURE.getPredicate());
}
}

View file

@ -1330,5 +1330,4 @@ public final class StaticFilters {
static {
FILTER_CONTROLLED_CLUE.setLockedFilter(true);
}
}