diff --git a/forge-game/src/main/java/forge/game/ForgeScript.java b/forge-game/src/main/java/forge/game/ForgeScript.java index 77d107709ff..cf8b4e45b48 100644 --- a/forge-game/src/main/java/forge/game/ForgeScript.java +++ b/forge-game/src/main/java/forge/game/ForgeScript.java @@ -2,6 +2,7 @@ package forge.game; import com.google.common.collect.Iterables; +import forge.card.CardTypeView; import forge.card.ColorSet; import forge.card.MagicColor; import forge.card.mana.ManaAtom; @@ -20,6 +21,7 @@ import forge.game.spellability.SpellAbilityPredicates; import forge.game.spellability.TargetChoices; import forge.game.staticability.StaticAbility; import forge.game.staticability.StaticAbilityCastWithFlash; +import forge.game.staticability.StaticAbilityColorlessDamageSource; import forge.game.trigger.Trigger; import forge.game.zone.ZoneType; import forge.util.Expressions; @@ -33,16 +35,19 @@ public class ForgeScript { public static boolean cardStateHasProperty(CardState cardState, String property, Player sourceController, Card source, CardTraitBase spellAbility) { - final boolean isColorlessSource = cardState.getCard().hasKeyword("Colorless Damage Source", cardState); - final ColorSet colors = cardState.getCard().getColor(cardState); + + boolean withSource = property.endsWith("Source"); + final ColorSet colors; + if (withSource && StaticAbilityColorlessDamageSource.colorlessDamageSource(cardState)) { + colors = ColorSet.getNullColor(); + } else { + colors = cardState.getCard().getColor(cardState); + } + + final CardTypeView type = cardState.getTypeWithChanges(); if (property.contains("White") || property.contains("Blue") || property.contains("Black") || property.contains("Red") || property.contains("Green")) { boolean mustHave = !property.startsWith("non"); - boolean withSource = property.endsWith("Source"); - if (withSource && isColorlessSource) { - return false; - } - final String colorName = property.substring(mustHave ? 0 : 3, property.length() - (withSource ? 6 : 0)); int desiredColor = MagicColor.fromName(colorName); @@ -50,19 +55,11 @@ public class ForgeScript { return mustHave == hasColor; } else if (property.contains("Colorless")) { // ... Card is colorless boolean non = property.startsWith("non"); - boolean withSource = property.endsWith("Source"); - if (non && withSource && isColorlessSource) { - return false; - } return non != colors.isColorless(); - } else if (property.contains("MultiColor")) { + } else if (property.startsWith("MultiColor")) { // ... Card is multicolored - if (property.endsWith("Source") && isColorlessSource) - return false; - return property.startsWith("non") != colors.isMulticolor(); - } else if (property.contains("EnemyColor")) { - if (property.endsWith("Source") && isColorlessSource) - return false; + return colors.isMulticolor(); + } else if (property.startsWith("EnemyColor")) { if (colors.countColors() != 2) { return false; } @@ -73,44 +70,36 @@ public class ForgeScript { } } return false; - } else if (property.contains("AllColors")) { - if (property.endsWith("Source") && isColorlessSource) - return false; - return property.startsWith("non") != colors.isAllColors(); - } else if (property.contains("MonoColor")) { // ... Card is monocolored - if (property.endsWith("Source") && isColorlessSource) - return false; - return property.startsWith("non") != colors.isMonoColor(); + } else if (property.startsWith("AllColors")) { + return colors.isAllColors(); + } else if (property.startsWith("MonoColor")) { // ... Card is monocolored + return colors.isMonoColor(); } else if (property.startsWith("ChosenColor")) { - if (property.endsWith("Source") && isColorlessSource) - return false; return source.hasChosenColor() && colors.hasAnyColor(MagicColor.fromName(source.getChosenColor())); } else if (property.startsWith("AnyChosenColor")) { - if (property.endsWith("Source") && isColorlessSource) - return false; return source.hasChosenColor() && colors.hasAnyColor(ColorSet.fromNames(source.getChosenColors()).getColor()); } else if (property.equals("AssociatedWithChosenColor")) { final String color = source.getChosenColor(); switch (color) { case "white": - return cardState.getTypeWithChanges().getLandTypes().contains("Plains"); + return type.hasSubtype("Plains"); case "blue": - return cardState.getTypeWithChanges().getLandTypes().contains("Island"); + return type.hasSubtype("Island"); case "black": - return cardState.getTypeWithChanges().getLandTypes().contains("Swamp"); + return type.hasSubtype("Swamp"); case "red": - return cardState.getTypeWithChanges().getLandTypes().contains("Mountain"); + return type.hasSubtype("Mountain"); case "green": - return cardState.getTypeWithChanges().getLandTypes().contains("Forest"); + return type.hasSubtype("Forest"); default: return false; } } else if (property.equals("Outlaw")) { - return cardState.getTypeWithChanges().isOutlaw(); + return type.isOutlaw(); } else if (property.startsWith("non")) { // ... Other Card types - return !cardState.getTypeWithChanges().hasStringType(property.substring(3)); + return !type.hasStringType(property.substring(3)); } else if (property.equals("CostsPhyrexianMana")) { return cardState.getManaCost().hasPhyrexian(); } else if (property.startsWith("HasSVar")) { @@ -119,19 +108,19 @@ public class ForgeScript { } else if (property.equals("ChosenType")) { String chosenType = source.getChosenType(); if (chosenType.startsWith("Non")) { - return !cardState.getTypeWithChanges().hasStringType(StringUtils.capitalize(chosenType.substring(3))); + return !type.hasStringType(StringUtils.capitalize(chosenType.substring(3))); } - return cardState.getTypeWithChanges().hasStringType(chosenType); + return type.hasStringType(chosenType); } else if (property.equals("IsNotChosenType")) { - return !cardState.getTypeWithChanges().hasStringType(source.getChosenType()); + return !type.hasStringType(source.getChosenType()); } else if (property.equals("ChosenType2")) { - return cardState.getTypeWithChanges().hasStringType(source.getChosenType2()); + return type.hasStringType(source.getChosenType2()); } else if (property.equals("IsNotChosenType2")) { - return !cardState.getTypeWithChanges().hasStringType(source.getChosenType2()); + return !type.hasStringType(source.getChosenType2()); } else if (property.equals("NotedType")) { boolean found = false; for (String s : source.getNotedTypes()) { - if (cardState.getTypeWithChanges().hasStringType(s)) { + if (type.hasStringType(s)) { found = true; break; } @@ -187,7 +176,7 @@ public class ForgeScript { int x = AbilityUtils.calculateAmount(source, rhs, spellAbility); return Expressions.compare(y, property, x); - } else return cardState.getTypeWithChanges().hasStringType(property); + } else return type.hasStringType(property); } public static boolean spellAbilityHasProperty(SpellAbility sa, String property, Player sourceController, diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityColorlessDamageSource.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityColorlessDamageSource.java new file mode 100644 index 00000000000..4e8fbc6777c --- /dev/null +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityColorlessDamageSource.java @@ -0,0 +1,32 @@ +package forge.game.staticability; + +import forge.game.card.Card; +import forge.game.card.CardState; +import forge.game.zone.ZoneType; + +public class StaticAbilityColorlessDamageSource { + + static String MODE = "ColorlessDamageSource"; + + public static boolean colorlessDamageSource(final CardState state) { + final Card card = state.getCard(); + for (final Card ca : card.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.checkConditions(MODE)) { + continue; + } + if (applyColorlessDamageSource(stAb, card)) { + return true; + } + } + } + return false; + } + + public static boolean applyColorlessDamageSource(final StaticAbility stAb, final Card card) { + if (!stAb.matchesValidParam("ValidCard", card)) { + return false; + } + return true; + } +} diff --git a/forge-gui/res/cardsfolder/g/ghostly_flame.txt b/forge-gui/res/cardsfolder/g/ghostly_flame.txt index a437df3e23e..7ec1884bad6 100644 --- a/forge-gui/res/cardsfolder/g/ghostly_flame.txt +++ b/forge-gui/res/cardsfolder/g/ghostly_flame.txt @@ -1,6 +1,6 @@ Name:Ghostly Flame ManaCost:B R Types:Enchantment -S:Mode$ Continuous | Affected$ Permanent.Black,Permanent.Red,Spell.Red,Spell.Black | AffectedZone$ Stack,Battlefield | AddHiddenKeyword$ Colorless Damage Source | Description$ Black and/or red permanents and spells are colorless sources of damage. +S:Mode$ ColorlessDamageSource | ValidCard$ Permanent.Black+inZoneBattlefield,Permanent.Red+inZoneBattlefield,Spell.Black+inZoneStack,Spell.Red+inZoneStack | Description$ Black and/or red permanents and spells are colorless sources of damage. SVar:NonStackingEffect:True Oracle:Black and/or red permanents and spells are colorless sources of damage. diff --git a/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java b/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java index 7257637fb3b..d776f1d4e8b 100644 --- a/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java +++ b/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java @@ -440,8 +440,7 @@ public final class CardScriptParser { "sameName", "namedCard", "NamedByRememberedPlayer", "Permanent", "ChosenCard", "nonChosenCard", "White", "Blue", "Black", "Red", "Green", "nonWhite", "nonBlue", "nonBlack", "nonRed", "nonGreen", - "Colorless", "nonColorless", "Multicolor", "nonMulticolor", - "Monocolor", "nonMonocolor", "ChosenColor", "AllChosenColors", + "Colorless", "nonColorless", "Multicolor", "Monocolor", "ChosenColor", "AllChosenColors", "AnyChosenColor", "DoubleFaced", "Flip", "YouCtrl", "YourTeamCtrl", "YouDontCtrl", "OppCtrl", "ChosenCtrl", "DefenderCtrl", "DefenderCtrlForRemembered", "DefendingPlayerCtrl",