Merge branch 'illusionary_terrain' into 'master'

Illusionary Terrain

See merge request core-developers/forge!3636
This commit is contained in:
Michael Kamensky
2021-01-25 04:47:57 +00:00
11 changed files with 68 additions and 1 deletions

View File

@@ -76,6 +76,7 @@ public abstract class GameState {
private final Map<Card, List<String>> cardToChosenClrs = new HashMap<>(); private final Map<Card, List<String>> cardToChosenClrs = new HashMap<>();
private final Map<Card, CardCollection> cardToChosenCards = new HashMap<>(); private final Map<Card, CardCollection> cardToChosenCards = new HashMap<>();
private final Map<Card, String> cardToChosenType = new HashMap<>(); private final Map<Card, String> cardToChosenType = new HashMap<>();
private final Map<Card, String> cardToChosenType2 = new HashMap<>();
private final Map<Card, List<String>> cardToRememberedId = new HashMap<>(); private final Map<Card, List<String>> cardToRememberedId = new HashMap<>();
private final Map<Card, List<String>> cardToImprintedId = new HashMap<>(); private final Map<Card, List<String>> cardToImprintedId = new HashMap<>();
private final Map<Card, String> cardToNamedCard = new HashMap<>(); private final Map<Card, String> cardToNamedCard = new HashMap<>();
@@ -323,6 +324,9 @@ public abstract class GameState {
if (!c.getChosenType().isEmpty()) { if (!c.getChosenType().isEmpty()) {
newText.append("|ChosenType:").append(c.getChosenType()); newText.append("|ChosenType:").append(c.getChosenType());
} }
if (!c.getChosenType2().isEmpty()) {
newText.append("|ChosenType2:").append(c.getChosenType2());
}
if (!c.getNamedCard().isEmpty()) { if (!c.getNamedCard().isEmpty()) {
newText.append("|NamedCard:").append(c.getNamedCard()); newText.append("|NamedCard:").append(c.getNamedCard());
} }
@@ -601,6 +605,7 @@ public abstract class GameState {
cardToChosenClrs.clear(); cardToChosenClrs.clear();
cardToChosenCards.clear(); cardToChosenCards.clear();
cardToChosenType.clear(); cardToChosenType.clear();
cardToChosenType2.clear();
cardToScript.clear(); cardToScript.clear();
cardAttackMap.clear(); cardAttackMap.clear();
@@ -1055,6 +1060,12 @@ public abstract class GameState {
c.setChosenType(entry.getValue()); c.setChosenType(entry.getValue());
} }
// Chosen type 2
for (Entry<Card, String> entry : cardToChosenType2.entrySet()) {
Card c = entry.getKey();
c.setChosenType2(entry.getValue());
}
// Named card // Named card
for (Entry<Card, String> entry : cardToNamedCard.entrySet()) { for (Entry<Card, String> entry : cardToNamedCard.entrySet()) {
Card c = entry.getKey(); Card c = entry.getKey();
@@ -1286,6 +1297,8 @@ public abstract class GameState {
cardToChosenClrs.put(c, Arrays.asList(info.substring(info.indexOf(':') + 1).split(","))); cardToChosenClrs.put(c, Arrays.asList(info.substring(info.indexOf(':') + 1).split(",")));
} else if (info.startsWith("ChosenType:")) { } else if (info.startsWith("ChosenType:")) {
cardToChosenType.put(c, info.substring(info.indexOf(':') + 1)); cardToChosenType.put(c, info.substring(info.indexOf(':') + 1));
} else if (info.startsWith("ChosenType2:")) {
cardToChosenType2.put(c, info.substring(info.indexOf(':') + 1));
} else if (info.startsWith("ChosenCards:")) { } else if (info.startsWith("ChosenCards:")) {
CardCollection chosen = new CardCollection(); CardCollection chosen = new CardCollection();
String[] idlist = info.substring(info.indexOf(':') + 1).split(","); String[] idlist = info.substring(info.indexOf(':') + 1).split(",");

View File

@@ -336,6 +336,9 @@ public class GameCopier {
if (!c.getChosenType().isEmpty()) { if (!c.getChosenType().isEmpty()) {
newCard.setChosenType(c.getChosenType()); newCard.setChosenType(c.getChosenType());
} }
if (!c.getChosenType2().isEmpty()) {
newCard.setChosenType2(c.getChosenType2());
}
if (c.getChosenColors() != null) { if (c.getChosenColors() != null) {
newCard.setChosenColors(Lists.newArrayList(c.getChosenColors())); newCard.setChosenColors(Lists.newArrayList(c.getChosenColors()));
} }

View File

@@ -73,6 +73,10 @@ public class ForgeScript {
return cardState.getTypeWithChanges().hasStringType(source.getChosenType()); return cardState.getTypeWithChanges().hasStringType(source.getChosenType());
} else if (property.equals("IsNotChosenType")) { } else if (property.equals("IsNotChosenType")) {
return !cardState.getTypeWithChanges().hasStringType(source.getChosenType()); return !cardState.getTypeWithChanges().hasStringType(source.getChosenType());
} else if (property.equals("ChosenType2")) {
return cardState.getTypeWithChanges().hasStringType(source.getChosenType2());
} else if (property.equals("IsNotChosenType2")) {
return !cardState.getTypeWithChanges().hasStringType(source.getChosenType2());
} else if (property.startsWith("HasSubtype")) { } else if (property.startsWith("HasSubtype")) {
final String subType = property.substring(11); final String subType = property.substring(11);
return cardState.getTypeWithChanges().hasSubtype(subType); return cardState.getTypeWithChanges().hasSubtype(subType);

View File

@@ -64,7 +64,11 @@ public class ChooseTypeEffect extends SpellAbilityEffect {
for (final Player p : tgtPlayers) { for (final Player p : tgtPlayers) {
if ((tgt == null) || p.canBeTargetedBy(sa)) { if ((tgt == null) || p.canBeTargetedBy(sa)) {
String choice = p.getController().chooseSomeType(type, sa, validTypes, invalidTypes); String choice = p.getController().chooseSomeType(type, sa, validTypes, invalidTypes);
if (!sa.hasParam("Secondary")) {
card.setChosenType(choice); card.setChosenType(choice);
} else {
card.setChosenType2(choice);
}
} }
} }
} }

View File

@@ -53,6 +53,7 @@ public class CleanUpEffect extends SpellAbilityEffect {
} }
if (sa.hasParam("ClearChosenType")) { if (sa.hasParam("ClearChosenType")) {
source.setChosenType(""); source.setChosenType("");
source.setChosenType2("");
} }
if (sa.hasParam("ClearChosenColor")) { if (sa.hasParam("ClearChosenColor")) {
source.setChosenColors(null); source.setChosenColors(null);

View File

@@ -228,6 +228,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private String originalText = "", text = ""; private String originalText = "", text = "";
private String chosenType = ""; private String chosenType = "";
private String chosenType2 = "";
private List<String> chosenColors; private List<String> chosenColors;
private String chosenName = ""; private String chosenName = "";
private String chosenName2 = ""; private String chosenName2 = "";
@@ -1469,6 +1470,20 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return chosenType != null && !chosenType.isEmpty(); return chosenType != null && !chosenType.isEmpty();
} }
// used by card Illusionary Terrain
public final String getChosenType2() {
return chosenType2;
}
public final void setChosenType2(final String s) {
chosenType2 = s;
view.updateChosenType2(this);
}
public final boolean hasChosenType2() {
return chosenType2 != null && !chosenType2.isEmpty();
}
public final String getChosenColor() { public final String getChosenColor() {
if (hasChosenColor()) { if (hasChosenColor()) {
return chosenColors.get(0); return chosenColors.get(0);

View File

@@ -306,6 +306,13 @@ public class CardView extends GameEntityView {
set(TrackableProperty.ChosenType, c.getChosenType()); set(TrackableProperty.ChosenType, c.getChosenType());
} }
public String getChosenType2() {
return get(TrackableProperty.ChosenType2);
}
void updateChosenType2(Card c) {
set(TrackableProperty.ChosenType2, c.getChosenType2());
}
public String getChosenNumber() { public String getChosenNumber() {
return get(TrackableProperty.ChosenNumber); return get(TrackableProperty.ChosenNumber);
} }

View File

@@ -367,6 +367,9 @@ public final class StaticAbilityContinuous {
if (input.equals("ChosenType") && !hostCard.hasChosenType()) { if (input.equals("ChosenType") && !hostCard.hasChosenType()) {
return true; return true;
} }
if (input.equals("ChosenType2") && !hostCard.hasChosenType2()) {
return true;
}
if (input.equals("ImprintedCreatureType")) { if (input.equals("ImprintedCreatureType")) {
if (hostCard.hasImprintedCard()) { if (hostCard.hasImprintedCard()) {
newTypes.addAll(hostCard.getImprintedCards().getLast().getType().getCreatureTypes()); newTypes.addAll(hostCard.getImprintedCards().getLast().getType().getCreatureTypes());
@@ -385,6 +388,9 @@ public final class StaticAbilityContinuous {
addTypes = Lists.transform(addTypes, new Function<String, String>() { addTypes = Lists.transform(addTypes, new Function<String, String>() {
@Override @Override
public String apply(String input) { public String apply(String input) {
if (hostCard.hasChosenType2()) {
input = input.replaceAll("ChosenType2", hostCard.getChosenType2());
}
if (hostCard.hasChosenType()) { if (hostCard.hasChosenType()) {
input = input.replaceAll("ChosenType", hostCard.getChosenType()); input = input.replaceAll("ChosenType", hostCard.getChosenType());
} }

View File

@@ -48,6 +48,7 @@ public enum TrackableProperty {
LethalDamage(TrackableTypes.IntegerType), LethalDamage(TrackableTypes.IntegerType),
ShieldCount(TrackableTypes.IntegerType), ShieldCount(TrackableTypes.IntegerType),
ChosenType(TrackableTypes.StringType), ChosenType(TrackableTypes.StringType),
ChosenType2(TrackableTypes.StringType),
ChosenColors(TrackableTypes.StringListType), ChosenColors(TrackableTypes.StringListType),
ChosenCards(TrackableTypes.CardViewCollectionType), ChosenCards(TrackableTypes.CardViewCollectionType),
ChosenNumber(TrackableTypes.StringType), ChosenNumber(TrackableTypes.StringType),

View File

@@ -0,0 +1,10 @@
Name:Illusionary Terrain
ManaCost:U U
Types:Enchantment
K:Cumulative upkeep:2
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigChooseType1 | TriggerDescription$ As Illusionary Terrain enters the battlefield, choose two basic land types.
SVar:TrigChooseType1:DB$ ChooseType | Defined$ You | Type$ Basic Land | SubAbility$ ChooseType2
SVar:ChooseType2:DB$ ChooseType | Defined$ You | Type$ Basic Land | Secondary$ True
S:Mode$ Continuous | Affected$ Land.Basic+ChosenType | AddType$ ChosenType2 | RemoveLandTypes$ True | Description$ Basic lands of the first chosen type are the second chosen type.
AI:RemoveDeck:All
Oracle:Cumulative upkeep {2} (At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it.)\nAs Illusionary Terrain enters the battlefield, choose two basic land types.\nBasic lands of the first chosen type are the second chosen type.

View File

@@ -393,6 +393,9 @@ public class CardDetailUtil {
} }
area.append("(chosen type: "); area.append("(chosen type: ");
area.append(card.getChosenType()); area.append(card.getChosenType());
if (!card.getChosenType2().isEmpty()) {
area.append(", ").append(card.getChosenType2());
}
area.append(")"); area.append(")");
} }