mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-13 01:08:06 +00:00
build ValidTgtsDesc via Lang (#9063)
* build ValidTgtsDesc via Lang * use buildValidDesc for AuraSpells * Add ValidTgtsDesc to GUI message
This commit is contained in:
@@ -2,6 +2,8 @@ package forge.util;
|
|||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.card.CardType;
|
||||||
import forge.util.lang.*;
|
import forge.util.lang.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
@@ -9,6 +11,7 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static library containing language-related utility methods.
|
* Static library containing language-related utility methods.
|
||||||
@@ -216,4 +219,19 @@ public abstract class Lang {
|
|||||||
}
|
}
|
||||||
return name.split(" ")[0];
|
return name.split(" ")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String buildValidDesc(List<String> valid, boolean multiple) {
|
||||||
|
return joinHomogenous(valid.stream().map(s -> formatValidDesc(s)).collect(Collectors.toList()), null, multiple ? "and/or" : "or");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String formatValidDesc(String valid) {
|
||||||
|
List<String> commonStuff = List.of(
|
||||||
|
//list of common one word non-core type ValidTgts that should be lowercase in the target prompt
|
||||||
|
"Player", "Opponent", "Card", "Spell", "Permanent"
|
||||||
|
);
|
||||||
|
if (commonStuff.contains(valid) || CardType.isACardType(valid)) {
|
||||||
|
valid = valid.toLowerCase();
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public abstract class CardTraitBase implements GameObject, IHasCardView, IHasSVa
|
|||||||
/** Keys of descriptive (text) parameters. */
|
/** Keys of descriptive (text) parameters. */
|
||||||
private static final ImmutableList<String> descriptiveKeys = ImmutableList.<String>builder()
|
private static final ImmutableList<String> descriptiveKeys = ImmutableList.<String>builder()
|
||||||
.add("Description", "SpellDescription", "StackDescription", "TriggerDescription")
|
.add("Description", "SpellDescription", "StackDescription", "TriggerDescription")
|
||||||
.add("ChangeTypeDesc")
|
.add("ChangeTypeDesc", "ValidTgtsDesc")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.game.ability;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.card.CardType;
|
|
||||||
import forge.game.CardTraitBase;
|
import forge.game.CardTraitBase;
|
||||||
import forge.game.IHasSVars;
|
import forge.game.IHasSVars;
|
||||||
import forge.game.ability.effects.CharmEffect;
|
import forge.game.ability.effects.CharmEffect;
|
||||||
@@ -34,7 +33,6 @@ import forge.util.FileSection;
|
|||||||
import io.sentry.Breadcrumb;
|
import io.sentry.Breadcrumb;
|
||||||
import io.sentry.Sentry;
|
import io.sentry.Sentry;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -317,89 +315,8 @@ public final class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static TargetRestrictions readTarget(Map<String, String> mapParams) {
|
private static TargetRestrictions readTarget(Map<String, String> mapParams) {
|
||||||
final String min = mapParams.getOrDefault("TargetMin", "1");
|
|
||||||
final String max = mapParams.getOrDefault("TargetMax", "1");
|
|
||||||
|
|
||||||
// TgtPrompt should only be needed for more complicated ValidTgts
|
// TgtPrompt should only be needed for more complicated ValidTgts
|
||||||
String tgtWhat = mapParams.get("ValidTgts");
|
return new TargetRestrictions(mapParams);
|
||||||
final String prompt;
|
|
||||||
if (mapParams.containsKey("TgtPrompt")) {
|
|
||||||
prompt = mapParams.get("TgtPrompt");
|
|
||||||
} else if (tgtWhat.equals("Any")) {
|
|
||||||
prompt = "Select any target";
|
|
||||||
} else {
|
|
||||||
final String[] commonStuff = new String[] {
|
|
||||||
//list of common one word non-core type ValidTgts that should be lowercase in the target prompt
|
|
||||||
"Player", "Opponent", "Card", "Spell", "Permanent"
|
|
||||||
};
|
|
||||||
if (Arrays.asList(commonStuff).contains(tgtWhat) || CardType.CoreType.isValidEnum(tgtWhat)) {
|
|
||||||
tgtWhat = tgtWhat.toLowerCase();
|
|
||||||
}
|
|
||||||
prompt = "Select target " + tgtWhat;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetRestrictions abTgt = new TargetRestrictions(prompt, mapParams.get("ValidTgts").split(","), min, max);
|
|
||||||
|
|
||||||
if (mapParams.containsKey("TgtZone")) {
|
|
||||||
// if Targeting something not in play, this Key should be set
|
|
||||||
abTgt.setZone(ZoneType.listValueOf(mapParams.get("TgtZone")));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapParams.containsKey("MaxTotalTargetCMC")) {
|
|
||||||
// only target cards up to a certain total max CMC
|
|
||||||
abTgt.setMaxTotalCMC(mapParams.get("MaxTotalTargetCMC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapParams.containsKey("MaxTotalTargetPower")) {
|
|
||||||
// only target cards up to a certain total max power
|
|
||||||
abTgt.setMaxTotalPower(mapParams.get("MaxTotalTargetPower"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TargetValidTargeting most for Counter: e.g. target spell that targets X.
|
|
||||||
if (mapParams.containsKey("TargetValidTargeting")) {
|
|
||||||
abTgt.setSAValidTargeting(mapParams.get("TargetValidTargeting"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapParams.containsKey("TargetUnique")) {
|
|
||||||
abTgt.setUniqueTargets(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithoutSameCreatureType")) {
|
|
||||||
abTgt.setWithoutSameCreatureType(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithSameCreatureType")) {
|
|
||||||
abTgt.setWithSameCreatureType(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithSameCardType")) {
|
|
||||||
abTgt.setWithSameCardType(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithSameController")) {
|
|
||||||
abTgt.setSameController(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithDifferentControllers")) {
|
|
||||||
abTgt.setDifferentControllers(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsForEachPlayer")) {
|
|
||||||
abTgt.setForEachPlayer(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithDifferentCMC")) {
|
|
||||||
abTgt.setDifferentCMC(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithDifferentNames")) {
|
|
||||||
abTgt.setDifferentNames(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsWithEqualToughness")) {
|
|
||||||
abTgt.setEqualToughness(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetsAtRandom")) {
|
|
||||||
abTgt.setRandomTarget(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("RandomNumTargets")) {
|
|
||||||
abTgt.setRandomNumTargets(true);
|
|
||||||
}
|
|
||||||
if (mapParams.containsKey("TargetingPlayer")) {
|
|
||||||
abTgt.setMandatory(true);
|
|
||||||
}
|
|
||||||
return abTgt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import com.google.common.collect.Iterables;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.card.CardType;
|
|
||||||
import forge.game.*;
|
import forge.game.*;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
@@ -31,7 +30,6 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ChangeZoneEffect extends SpellAbilityEffect {
|
public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||||
|
|
||||||
@@ -119,8 +117,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
type = Lang.joinHomogenous(tgts);
|
type = Lang.joinHomogenous(tgts);
|
||||||
defined = true;
|
defined = true;
|
||||||
} else if (sa.hasParam("ChangeType") && !sa.getParam("ChangeType").equals("Card")) {
|
} else if (sa.hasParam("ChangeType") && !sa.getParam("ChangeType").equals("Card")) {
|
||||||
List<String> typeList = Arrays.stream(sa.getParam("ChangeType").split(",")).map(ct -> CardType.isACardType(ct) ? ct.toLowerCase() : ct).collect(Collectors.toList());
|
type = Lang.getInstance().buildValidDesc(Arrays.asList(sa.getParam("ChangeType").split(",")), num != 1);
|
||||||
type = Lang.joinHomogenous(typeList, null, num == 1 ? "or" : "and/or");
|
|
||||||
}
|
}
|
||||||
final String cardTag = type.contains("card") ? "" : " card";
|
final String cardTag = type.contains("card") ? "" : " card";
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.card.RemoveType;
|
import forge.card.RemoveType;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
@@ -37,7 +38,7 @@ public class EarthbendEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildSpellAbility(final SpellAbility sa) {
|
public void buildSpellAbility(final SpellAbility sa) {
|
||||||
TargetRestrictions abTgt = new TargetRestrictions("Select target land you control", "Land.YouCtrl".split(","), "1", "1");
|
TargetRestrictions abTgt = new TargetRestrictions(Map.of("ValidTgtsDesc", "land you control", "ValidTgts", "Land.YouCtrl"));
|
||||||
sa.setTargetRestrictions(abTgt);
|
sa.setTargetRestrictions(abTgt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
|
|||||||
if (hasSVar("AttachAIValid")) { // TODO combine with AttachAITgts
|
if (hasSVar("AttachAIValid")) { // TODO combine with AttachAITgts
|
||||||
extra += " | AIValid$ " + getSVar("AttachAIValid");
|
extra += " | AIValid$ " + getSVar("AttachAIValid");
|
||||||
}
|
}
|
||||||
String st = "SP$ Attach | ValidTgts$ Card.CanBeEnchantedBy,Player.CanBeEnchantedBy | TgtZone$ Battlefield,Graveyard | TgtPrompt$ Select target " + desc + extra;
|
String st = "SP$ Attach | ValidTgts$ Card.CanBeEnchantedBy,Player.CanBeEnchantedBy | TgtZone$ Battlefield,Graveyard | ValidTgtsDesc$ " + desc + extra;
|
||||||
auraAbility = AbilityFactory.getAbility(st, this);
|
auraAbility = AbilityFactory.getAbility(st, this);
|
||||||
auraAbility.setIntrinsic(true);
|
auraAbility.setIntrinsic(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package forge.game.keyword;
|
package forge.game.keyword;
|
||||||
|
|
||||||
import forge.card.CardType;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import forge.util.Lang;
|
||||||
|
|
||||||
public class KeywordWithType extends KeywordInstance<KeywordWithType> {
|
public class KeywordWithType extends KeywordInstance<KeywordWithType> {
|
||||||
protected String type = null;
|
protected String type = null;
|
||||||
@@ -31,17 +33,19 @@ public class KeywordWithType extends KeywordInstance<KeywordWithType> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
descType = type = details;
|
descType = type = details;
|
||||||
|
boolean multiple = switch(getKeyword()) {
|
||||||
|
case AFFINITY -> true;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
descType = Lang.getInstance().buildValidDesc(Arrays.asList(type.split(",")), multiple);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CardType.isACardType(descType) || "Permanent".equals(descType) || "Player".equals(descType) || "Opponent".equals(descType)) {
|
if (descType.equalsIgnoreCase("Outlaw")) {
|
||||||
descType = descType.toLowerCase();
|
|
||||||
} else if (descType.equalsIgnoreCase("Outlaw")) {
|
|
||||||
reminderType = "Assassin, Mercenary, Pirate, Rogue, and/or Warlock";
|
reminderType = "Assassin, Mercenary, Pirate, Rogue, and/or Warlock";
|
||||||
} else if (type.equalsIgnoreCase("historic permanent")) {
|
} else if (type.equalsIgnoreCase("historic permanent")) {
|
||||||
reminderType = "artifact, legendary, and/or Saga permanent";
|
reminderType = "artifact, legendary, and/or Saga permanent";
|
||||||
}
|
} else {
|
||||||
if (reminderType == null) {
|
reminderType = descType;
|
||||||
reminderType = type;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.game.spellability;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.Lang;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +50,7 @@ public class TargetRestrictions {
|
|||||||
private String[] originalValidTgts,
|
private String[] originalValidTgts,
|
||||||
validTgts;
|
validTgts;
|
||||||
private String uiPrompt = "";
|
private String uiPrompt = "";
|
||||||
|
private String validTgtsDesc = "";
|
||||||
private List<ZoneType> tgtZone = Arrays.asList(ZoneType.Battlefield);
|
private List<ZoneType> tgtZone = Arrays.asList(ZoneType.Battlefield);
|
||||||
|
|
||||||
// The target SA of this SA must be targeting a Valid X
|
// The target SA of this SA must be targeting a Valid X
|
||||||
@@ -125,12 +128,87 @@ public class TargetRestrictions {
|
|||||||
* @param max
|
* @param max
|
||||||
* a {@link java.lang.String} object.
|
* a {@link java.lang.String} object.
|
||||||
*/
|
*/
|
||||||
public TargetRestrictions(final String prompt, final String[] valid, final String min, final String max) {
|
public TargetRestrictions(Map<String, String> mapParams) {
|
||||||
this.uiPrompt = prompt;
|
this.originalValidTgts = mapParams.get("ValidTgts").split(",");
|
||||||
this.originalValidTgts = valid;
|
|
||||||
this.validTgts = this.originalValidTgts.clone();
|
this.validTgts = this.originalValidTgts.clone();
|
||||||
this.minTargets = min;
|
this.minTargets = mapParams.getOrDefault("TargetMin", "1");
|
||||||
this.maxTargets = max;
|
this.maxTargets = mapParams.getOrDefault("TargetMax", "1");
|
||||||
|
|
||||||
|
if (mapParams.containsKey("ValidTgtsDesc")) {
|
||||||
|
this.validTgtsDesc = mapParams.get("ValidTgtsDesc");
|
||||||
|
} else if ("Any".equals(mapParams.get("ValidTgts"))) {
|
||||||
|
this.validTgtsDesc = "damage target";
|
||||||
|
} else {
|
||||||
|
this.validTgtsDesc = Lang.getInstance().buildValidDesc(Arrays.asList(this.validTgts), maxTargets != "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapParams.containsKey("TgtPrompt")) {
|
||||||
|
this.uiPrompt = mapParams.get("TgtPrompt");
|
||||||
|
} else if ("Any".equals(mapParams.get("ValidTgts"))) {
|
||||||
|
this.uiPrompt = "Select any target";
|
||||||
|
} else {
|
||||||
|
this.uiPrompt = "Select target " + validTgtsDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapParams.containsKey("TgtZone")) {
|
||||||
|
// if Targeting something not in play, this Key should be set
|
||||||
|
setZone(ZoneType.listValueOf(mapParams.get("TgtZone")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapParams.containsKey("MaxTotalTargetCMC")) {
|
||||||
|
// only target cards up to a certain total max CMC
|
||||||
|
setMaxTotalCMC(mapParams.get("MaxTotalTargetCMC"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapParams.containsKey("MaxTotalTargetPower")) {
|
||||||
|
// only target cards up to a certain total max power
|
||||||
|
setMaxTotalPower(mapParams.get("MaxTotalTargetPower"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetValidTargeting most for Counter: e.g. target spell that targets X.
|
||||||
|
if (mapParams.containsKey("TargetValidTargeting")) {
|
||||||
|
setSAValidTargeting(mapParams.get("TargetValidTargeting"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapParams.containsKey("TargetUnique")) {
|
||||||
|
setUniqueTargets(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithoutSameCreatureType")) {
|
||||||
|
setWithoutSameCreatureType(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithSameCreatureType")) {
|
||||||
|
setWithSameCreatureType(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithSameCardType")) {
|
||||||
|
setWithSameCardType(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithSameController")) {
|
||||||
|
setSameController(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithDifferentControllers")) {
|
||||||
|
setDifferentControllers(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsForEachPlayer")) {
|
||||||
|
setForEachPlayer(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithDifferentCMC")) {
|
||||||
|
setDifferentCMC(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithDifferentNames")) {
|
||||||
|
setDifferentNames(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsWithEqualToughness")) {
|
||||||
|
setEqualToughness(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetsAtRandom")) {
|
||||||
|
setRandomTarget(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("RandomNumTargets")) {
|
||||||
|
setRandomNumTargets(true);
|
||||||
|
}
|
||||||
|
if (mapParams.containsKey("TargetingPlayer")) {
|
||||||
|
setMandatory(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean getMandatory() {
|
public final boolean getMandatory() {
|
||||||
@@ -175,6 +253,10 @@ public class TargetRestrictions {
|
|||||||
return this.validTgts;
|
return this.validTgts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final String getValidDesc() {
|
||||||
|
return this.validTgtsDesc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* getVTSelection.
|
* getVTSelection.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Name:Corrupted Roots
|
Name:Corrupted Roots
|
||||||
ManaCost:B
|
ManaCost:B
|
||||||
Types:Enchantment Aura
|
Types:Enchantment Aura
|
||||||
K:Enchant:Land
|
K:Enchant:Forest,Plains
|
||||||
SVar:AttachAILogic:Curse
|
SVar:AttachAILogic:Curse
|
||||||
T:Mode$ Taps | ValidCard$ Card.AttachedBy | TriggerZones$ Battlefield | Execute$ TrigLose | TriggerDescription$ Whenever enchanted land becomes tapped, its controller loses 2 life.
|
T:Mode$ Taps | ValidCard$ Card.AttachedBy | TriggerZones$ Battlefield | Execute$ TrigLose | TriggerDescription$ Whenever enchanted land becomes tapped, its controller loses 2 life.
|
||||||
SVar:TrigLose:DB$ LoseLife | Defined$ TriggeredCardController | LifeAmount$ 2
|
SVar:TrigLose:DB$ LoseLife | Defined$ TriggeredCardController | LifeAmount$ 2
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Name:Malicious Advice
|
Name:Malicious Advice
|
||||||
ManaCost:X U B
|
ManaCost:X U B
|
||||||
Types:Instant
|
Types:Instant
|
||||||
A:SP$ Tap | TargetMin$ X | TargetMax$ X | ValidTgts$ Artifact,Creature,Land | TgtPrompt$ Select X target artifacts, creatures, or lands | SpellDescription$ Tap X target artifacts, creatures, and/or lands. You lose X life. | SubAbility$ Drain
|
A:SP$ Tap | TargetMin$ X | TargetMax$ X | ValidTgts$ Artifact,Creature,Land | SpellDescription$ Tap X target artifacts, creatures, and/or lands. You lose X life. | SubAbility$ Drain
|
||||||
SVar:Drain:DB$ LoseLife | LifeAmount$ X
|
SVar:Drain:DB$ LoseLife | LifeAmount$ X
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!choices.contains(card)) {
|
if (!choices.contains(card)) {
|
||||||
showMessage(sa.getHostCard() + " - The selected card is not a valid choice to be targeted.");
|
showMessage(sa.getHostCard() + " - The selected card is not " + Lang.nounWithAmount(1, tgt.getValidDesc()) + ".");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user