forked from External/mage
Rework affinity implementation (#13707)
* rework affinity implementation * move filters
This commit is contained in:
parent
2d237fdba1
commit
0b714946b0
41 changed files with 310 additions and 466 deletions
|
|
@ -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) {
|
||||
|
|
@ -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
|
||||
|
|
@ -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>";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
119
Mage/src/main/java/mage/constants/AffinityType.java
Normal file
119
Mage/src/main/java/mage/constants/AffinityType.java
Normal 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());
|
||||
}
|
||||
}
|
||||
|
|
@ -1330,5 +1330,4 @@ public final class StaticFilters {
|
|||
static {
|
||||
FILTER_CONTROLLED_CLUE.setLockedFilter(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue