From 51a0a9e70ad5b32febd01cf3b8cdb89a3c23abfa Mon Sep 17 00:00:00 2001 From: Hanmac Date: Sat, 26 May 2018 09:31:12 +0200 Subject: [PATCH] CardType: fixed seting specific SubTypes --- .../main/java/forge/ai/ComputerUtilCard.java | 4 +- .../main/java/forge/ai/ability/AnimateAi.java | 93 +++++-------------- .../main/java/forge/card/CardChangedType.java | 17 +++- .../src/main/java/forge/card/CardType.java | 74 ++++++++++++++- .../main/java/forge/game/StaticEffect.java | 2 +- .../ability/effects/AnimateAllEffect.java | 42 ++++++--- .../game/ability/effects/AnimateEffect.java | 46 +++++---- .../ability/effects/AnimateEffectBase.java | 47 +++++----- .../ability/effects/CopyPermanentEffect.java | 2 +- .../game/ability/effects/DebuffEffect.java | 2 +- .../ability/effects/ProtectAllEffect.java | 2 +- .../game/ability/effects/ProtectEffect.java | 5 +- .../game/ability/effects/PumpAllEffect.java | 25 +++-- .../game/ability/effects/PumpEffect.java | 4 +- .../src/main/java/forge/game/card/Card.java | 83 +++++++++++------ .../java/forge/game/card/CardFactoryUtil.java | 1 + .../forge/game/keyword/KeywordsChange.java | 26 ++++-- .../main/java/forge/game/mana/ManaPool.java | 2 +- .../main/java/forge/game/player/Player.java | 5 +- .../forge/game/spellability/SpellAbility.java | 9 ++ .../game/staticability/StaticAbility.java | 4 +- .../StaticAbilityContinuous.java | 51 +++++++--- 22 files changed, 346 insertions(+), 200 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 1e05d7a55e4..ae3a451a74a 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1573,7 +1573,7 @@ public class ComputerUtilCard { pumped.addNewPT(c.getCurrentPower(), c.getCurrentToughness(), timestamp); pumped.addTempPowerBoost(c.getTempPowerBoost() + power + berserkPower); pumped.addTempToughnessBoost(c.getTempToughnessBoost() + toughness); - pumped.addChangedCardKeywords(kws, new ArrayList(), false, timestamp); + pumped.addChangedCardKeywords(kws, null, false, false, timestamp); Set types = c.getCounters().keySet(); for(CounterType ct : types) { pumped.addCounterFireNoEvents(ct, c.getCounters(ct), c, true); @@ -1596,7 +1596,7 @@ public class ComputerUtilCard { } } final long timestamp2 = c.getGame().getNextTimestamp(); //is this necessary or can the timestamp be re-used? - pumped.addChangedCardKeywordsInternal(toCopy, Lists.newArrayList(), false, timestamp2, true); + pumped.addChangedCardKeywordsInternal(toCopy, null, false, false, timestamp2, true); ComputerUtilCard.applyStaticContPT(ai.getGame(), pumped, new CardCollection(c)); return pumped; } diff --git a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java index 28e8fb5bb9c..76fdbbd3d0d 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java @@ -23,12 +23,12 @@ import forge.game.staticability.StaticAbilityLayer; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; import forge.game.zone.ZoneType; -import forge.util.collect.FCollectionView; import java.util.Arrays; import java.util.List; import java.util.Map; +import forge.game.ability.effects.AnimateEffectBase; /** *

@@ -363,11 +363,11 @@ public class AnimateAi extends SpellAbilityAi { card.setSickness(hasOriginalCardSickness); // AF specific sa - int power = -1; + Integer power = null; if (sa.hasParam("Power")) { power = AbilityUtils.calculateAmount(source, sa.getParam("Power"), sa); } - int toughness = -1; + Integer toughness = null; if (sa.hasParam("Toughness")) { toughness = AbilityUtils.calculateAmount(source, sa.getParam("Toughness"), sa); } @@ -453,65 +453,7 @@ public class AnimateAi extends SpellAbilityAi { sVars.addAll(Arrays.asList(sa.getParam("sVars").split(","))); } - // duplicating AnimateEffectBase.doAnimate - boolean removeSuperTypes = false; - boolean removeCardTypes = false; - boolean removeSubTypes = false; - boolean removeCreatureTypes = false; - boolean removeArtifactTypes = false; - - if (sa.hasParam("OverwriteTypes")) { - removeSuperTypes = true; - removeCardTypes = true; - removeSubTypes = true; - removeCreatureTypes = true; - removeArtifactTypes = true; - } - - if (sa.hasParam("KeepSupertypes")) { - removeSuperTypes = false; - } - - if (sa.hasParam("KeepCardTypes")) { - removeCardTypes = false; - } - - if (sa.hasParam("RemoveSuperTypes")) { - removeSuperTypes = true; - } - - if (sa.hasParam("RemoveCardTypes")) { - removeCardTypes = true; - } - - if (sa.hasParam("RemoveSubTypes")) { - removeSubTypes = true; - } - - if (sa.hasParam("RemoveCreatureTypes")) { - removeCreatureTypes = true; - } - - if (sa.hasParam("RemoveArtifactTypes")) { - removeArtifactTypes = true; - } - - if ((power != -1) || (toughness != -1)) { - card.addNewPT(power, toughness, timestamp); - } - - if (!types.isEmpty() || !removeTypes.isEmpty() || removeCreatureTypes) { - card.addChangedCardTypes(types, removeTypes, removeSuperTypes, removeCardTypes, removeSubTypes, - removeCreatureTypes, removeArtifactTypes, timestamp); - } - - card.addChangedCardKeywords(keywords, removeKeywords, sa.hasParam("RemoveAllAbilities"), timestamp); - - for (final String k : hiddenKeywords) { - card.addHiddenExtrinsicKeyword(k); - } - - card.addColor(finalDesc, !sa.hasParam("OverwriteColors"), timestamp); + AnimateEffectBase.doAnimate(card, sa, power, toughness, types, removeTypes, finalDesc, keywords, removeKeywords, hiddenKeywords, timestamp); // back to duplicating AnimateEffect.resolve // TODO will all these abilities/triggers/replacements/etc. lead to @@ -521,10 +463,14 @@ public class AnimateAi extends SpellAbilityAi { boolean clearAbilities = sa.hasParam("OverwriteAbilities"); boolean clearSpells = sa.hasParam("OverwriteSpells"); boolean removeAll = sa.hasParam("RemoveAllAbilities"); + boolean removeIntrinsic = sa.hasParam("RemoveIntrinsicAbilities"); if (clearAbilities || clearSpells || removeAll) { for (final SpellAbility ab : card.getSpellAbilities()) { - if (removeAll || (ab.isAbility() && clearAbilities) || (ab.isSpell() && clearSpells)) { + if (removeAll + || (ab.isIntrinsic() && removeIntrinsic && !ab.isBasicLandAbility()) + || (ab.isAbility() && clearAbilities) + || (ab.isSpell() && clearSpells)) { card.removeSpellAbility(ab); removedAbilities.add(ab); } @@ -565,9 +511,11 @@ public class AnimateAi extends SpellAbilityAi { // suppress triggers from the animated card final List removedTriggers = Lists.newArrayList(); - if (sa.hasParam("OverwriteTriggers") || removeAll) { - final FCollectionView triggersToRemove = card.getTriggers(); - for (final Trigger trigger : triggersToRemove) { + if (sa.hasParam("OverwriteTriggers") || removeAll || removeIntrinsic) { + for (final Trigger trigger : card.getTriggers()) { + if (removeIntrinsic && !trigger.isIntrinsic()) { + continue; + } trigger.setSuppressed(true); removedTriggers.add(trigger); } @@ -603,9 +551,11 @@ public class AnimateAi extends SpellAbilityAi { // suppress static abilities from the animated card final List removedStatics = Lists.newArrayList(); - if (sa.hasParam("OverwriteStatics") || removeAll) { - final FCollectionView staticsToRemove = card.getStaticAbilities(); - for (final StaticAbility stAb : staticsToRemove) { + if (sa.hasParam("OverwriteStatics") || removeAll || removeIntrinsic) { + for (final StaticAbility stAb : card.getStaticAbilities()) { + if (removeIntrinsic && !stAb.isIntrinsic()) { + continue; + } stAb.setTemporarilySuppressed(true); removedStatics.add(stAb); } @@ -613,8 +563,11 @@ public class AnimateAi extends SpellAbilityAi { // suppress static abilities from the animated card final List removedReplacements = Lists.newArrayList(); - if (sa.hasParam("OverwriteReplacements") || removeAll) { + if (sa.hasParam("OverwriteReplacements") || removeAll || removeIntrinsic) { for (final ReplacementEffect re : card.getReplacementEffects()) { + if (removeIntrinsic && !re.isIntrinsic()) { + continue; + } re.setTemporarilySuppressed(true); removedReplacements.add(re); } diff --git a/forge-core/src/main/java/forge/card/CardChangedType.java b/forge-core/src/main/java/forge/card/CardChangedType.java index 1aae3bd41fa..6e855548598 100644 --- a/forge-core/src/main/java/forge/card/CardChangedType.java +++ b/forge-core/src/main/java/forge/card/CardChangedType.java @@ -32,19 +32,24 @@ public class CardChangedType { private final boolean removeSuperTypes; private final boolean removeCardTypes; private final boolean removeSubTypes; + private final boolean removeLandTypes; private final boolean removeCreatureTypes; private final boolean removeArtifactTypes; + private final boolean removeEnchantmentTypes; public CardChangedType(final CardType addType0, final CardType removeType0, final boolean removeSuperType0, - final boolean removeCardType0, final boolean removeSubType0, final boolean removeCreatureType0, - final boolean removeArtifactType0) { + final boolean removeCardType0, final boolean removeSubType0, final boolean removeLandType0, + final boolean removeCreatureType0, final boolean removeArtifactType0, + final boolean removeEnchantmentTypes0) { addType = addType0; removeType = removeType0; removeSuperTypes = removeSuperType0; removeCardTypes = removeCardType0; removeSubTypes = removeSubType0; + removeLandTypes = removeLandType0; removeCreatureTypes = removeCreatureType0; removeArtifactTypes = removeArtifactType0; + removeEnchantmentTypes = removeEnchantmentTypes0; } public final CardType getAddType() { @@ -67,6 +72,10 @@ public class CardChangedType { return removeSubTypes; } + public final boolean isRemoveLandTypes() { + return removeLandTypes; + } + public final boolean isRemoveCreatureTypes() { return removeCreatureTypes; } @@ -74,4 +83,8 @@ public class CardChangedType { public final boolean isRemoveArtifactTypes() { return removeArtifactTypes; } + + public final boolean isRemoveEnchantmentTypes() { + return removeEnchantmentTypes; + } } diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index f01b9e59413..e3713cf1f1b 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -190,7 +190,7 @@ public final class CardType implements Comparable, CardTypeView { public boolean setCreatureTypes(Collection ctypes) { // if it isn't a creature then this has no effect - if (!coreTypes.contains(CoreType.Creature)) { + if (!isCreature() && !isTribal()) { return false; } boolean changed = Iterables.removeIf(subtypes, Predicates.IS_CREATURE_TYPE); @@ -236,7 +236,7 @@ public final class CardType implements Comparable, CardTypeView { final Set landTypes = Sets.newHashSet(); if (isLand()) { for (final String t : subtypes) { - if (isALandType(t) || isABasicLandType(t)) { + if (isALandType(t)) { landTypes.add(t); } } @@ -435,6 +435,9 @@ public final class CardType implements Comparable, CardTypeView { @Override public CardTypeView getTypeWithChanges(final Iterable changedCardTypes) { CardType newType = null; + if (Iterables.isEmpty(changedCardTypes)) { + return this; + } // we assume that changes are already correctly ordered (taken from TreeMap.values()) for (final CardChangedType ct : changedCardTypes) { if(null == newType) @@ -449,7 +452,10 @@ public final class CardType implements Comparable, CardTypeView { if (ct.isRemoveSubTypes()) { newType.subtypes.clear(); } - else { + else if (!newType.subtypes.isEmpty()) { + if (ct.isRemoveLandTypes()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_LAND_TYPE); + } if (ct.isRemoveCreatureTypes()) { Iterables.removeIf(newType.subtypes, Predicates.IS_CREATURE_TYPE); // need to remove AllCreatureTypes too when removing creature Types @@ -458,6 +464,9 @@ public final class CardType implements Comparable, CardTypeView { if (ct.isRemoveArtifactTypes()) { Iterables.removeIf(newType.subtypes, Predicates.IS_ARTIFACT_TYPE); } + if (ct.isRemoveEnchantmentTypes()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_ENCHANTMENT_TYPE); + } } if (ct.getRemoveType() != null) { newType.removeAll(ct.getRemoveType()); @@ -466,6 +475,28 @@ public final class CardType implements Comparable, CardTypeView { newType.addAll(ct.getAddType()); } } + // sanisfy subtypes + if (newType != null && !newType.subtypes.isEmpty()) { + if (!newType.isCreature() && !newType.isTribal()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_CREATURE_TYPE); + newType.subtypes.remove("AllCreatureTypes"); + } + if (!newType.isLand()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_LAND_TYPE); + } + if (!newType.isArtifact()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_ARTIFACT_TYPE); + } + if (!newType.isEnchantment()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_ENCHANTMENT_TYPE); + } + if (!newType.isInstant() && !newType.isSorcery()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_SPELL_TYPE); + } + if (!newType.isPlaneswalker() && !newType.isEmblem()) { + Iterables.removeIf(newType.subtypes, Predicates.IS_WALKER_TYPE); + } + } return newType == null ? this : newType; } @@ -574,6 +605,13 @@ public final class CardType implements Comparable, CardTypeView { public static final BiMap singularTypes = pluralTypes.inverse(); } public static class Predicates { + public static Predicate IS_LAND_TYPE = new Predicate() { + @Override + public boolean apply(String input) { + return CardType.isALandType(input); + } + }; + public static Predicate IS_ARTIFACT_TYPE = new Predicate() { @Override public boolean apply(String input) { @@ -587,6 +625,27 @@ public final class CardType implements Comparable, CardTypeView { return CardType.isACreatureType(input); } }; + + public static Predicate IS_ENCHANTMENT_TYPE = new Predicate() { + @Override + public boolean apply(String input) { + return CardType.isAnEnchantmentType(input); + } + }; + + public static Predicate IS_SPELL_TYPE = new Predicate() { + @Override + public boolean apply(String input) { + return CardType.isASpellType(input); + } + }; + + public static Predicate IS_WALKER_TYPE = new Predicate() { + @Override + public boolean apply(String input) { + return CardType.isAPlaneswalkerType(input); + } + }; } @@ -656,7 +715,7 @@ public final class CardType implements Comparable, CardTypeView { } public static boolean isALandType(final String cardType) { - return (Constant.LAND_TYPES.contains(cardType)); + return Constant.LAND_TYPES.contains(cardType) || isABasicLandType(cardType); } public static boolean isAPlaneswalkerType(final String cardType) { @@ -667,6 +726,13 @@ public final class CardType implements Comparable, CardTypeView { return (Constant.BASIC_TYPES.contains(cardType)); } + public static boolean isAnEnchantmentType(final String cardType) { + return (Constant.ENCHANTMENT_TYPES.contains(cardType)); + } + + public static boolean isASpellType(final String cardType) { + return (Constant.SPELL_TYPES.contains(cardType)); + } /** * If the input is a plural type, return the corresponding singular form. diff --git a/forge-game/src/main/java/forge/game/StaticEffect.java b/forge-game/src/main/java/forge/game/StaticEffect.java index 4462acce247..f01c811b022 100644 --- a/forge-game/src/main/java/forge/game/StaticEffect.java +++ b/forge-game/src/main/java/forge/game/StaticEffect.java @@ -1036,7 +1036,7 @@ public class StaticEffect { } // remove abilities - if (params.containsKey("RemoveAllAbilities")) { + if (params.containsKey("RemoveAllAbilities") || params.containsKey("RemoveIntrinsicAbilities")) { affectedCard.unSuppressCardTraits(); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java index 17b5a336eb1..0f3219c7e55 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateAllEffect.java @@ -25,6 +25,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import com.google.common.collect.ImmutableList; + public class AnimateAllEffect extends AnimateEffectBase { @Override @@ -144,6 +146,9 @@ public class AnimateAllEffect extends AnimateEffectBase { list = CardLists.getValidCards(list, valid.split(","), host.getController(), host, sa); + boolean removeAll = sa.hasParam("RemoveAllAbilities"); + boolean removeIntrinsic = sa.hasParam("RemoveIntrinsicAbilities"); + for (final Card c : list) { doAnimate(c, sa, power, toughness, types, removeTypes, finalDesc, keywords, removeKeywords, hiddenKeywords, timestamp); @@ -161,11 +166,14 @@ public class AnimateAllEffect extends AnimateEffectBase { // remove abilities final List removedAbilities = new ArrayList(); - if (sa.hasParam("OverwriteAbilities") || sa.hasParam("RemoveAllAbilities")) { + if (sa.hasParam("OverwriteAbilities") || removeAll || removeIntrinsic) { for (final SpellAbility ab : c.getSpellAbilities()) { if (ab.isAbility()) { - c.removeSpellAbility(ab); - removedAbilities.add(ab); + if (removeAll + || (ab.isIntrinsic() && removeIntrinsic && !ab.isBasicLandAbility())) { + ab.setTemporarilySuppressed(true); + removedAbilities.add(ab); + } } } } @@ -190,19 +198,24 @@ public class AnimateAllEffect extends AnimateEffectBase { // suppress triggers from the animated card final List removedTriggers = new ArrayList(); - if (sa.hasParam("OverwriteTriggers") || sa.hasParam("RemoveAllAbilities")) { + if (sa.hasParam("OverwriteTriggers") || removeAll || removeIntrinsic) { final FCollectionView triggersToRemove = c.getTriggers(); for (final Trigger trigger : triggersToRemove) { - trigger.setSuppressed(true); + if (removeIntrinsic && !trigger.isIntrinsic()) { + continue; + } + trigger.setSuppressed(true); // why this not TemporarilySuppressed? removedTriggers.add(trigger); } } // suppress static abilities from the animated card final List removedStatics = new ArrayList(); - if (sa.hasParam("OverwriteStatics") || sa.hasParam("RemoveAllAbilities")) { - final FCollectionView staticsToRemove = c.getStaticAbilities(); - for (final StaticAbility stAb : staticsToRemove) { + if (sa.hasParam("OverwriteStatics") || removeAll || removeIntrinsic) { + for (final StaticAbility stAb : c.getStaticAbilities()) { + if (removeIntrinsic && !stAb.isIntrinsic()) { + continue; + } stAb.setTemporarilySuppressed(true); removedStatics.add(stAb); } @@ -210,9 +223,11 @@ public class AnimateAllEffect extends AnimateEffectBase { // suppress static abilities from the animated card final List removedReplacements = new ArrayList(); - if (sa.hasParam("OverwriteReplacements") || sa.hasParam("RemoveAllAbilities")) { - final FCollectionView replacementsToRemove = c.getReplacementEffects(); - for (final ReplacementEffect re : replacementsToRemove) { + if (sa.hasParam("OverwriteReplacements") || removeAll || removeIntrinsic) { + for (final ReplacementEffect re : c.getReplacementEffects()) { + if (removeIntrinsic && !re.isIntrinsic()) { + continue; + } re.setTemporarilySuppressed(true); removedReplacements.add(re); } @@ -234,8 +249,11 @@ public class AnimateAllEffect extends AnimateEffectBase { public void run() { doUnanimate(c, sa, finalDesc, hiddenKeywords, addedAbilities, addedTriggers, addedReplacements, - false, removedAbilities, timestamp); + ImmutableList.of(), timestamp); + for (final SpellAbility sa : removedAbilities) { + sa.setTemporarilySuppressed(false); + } // give back suppressed triggers for (final Trigger t : removedTriggers) { t.setSuppressed(false); diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java index e2de4258f82..cb4429f3e25 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java @@ -18,7 +18,6 @@ import forge.game.spellability.SpellAbility; import forge.game.staticability.StaticAbility; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; -import forge.util.collect.FCollectionView; import java.util.Arrays; import java.util.List; @@ -162,21 +161,20 @@ public class AnimateEffect extends AnimateEffectBase { boolean clearAbilities = sa.hasParam("OverwriteAbilities"); boolean clearSpells = sa.hasParam("OverwriteSpells"); boolean removeAll = sa.hasParam("RemoveAllAbilities"); + boolean removeIntrinsic = sa.hasParam("RemoveIntrinsicAbilities"); if (clearAbilities || clearSpells || removeAll) { for (final SpellAbility ab : c.getSpellAbilities()) { - if (removeAll || (ab.isAbility() && clearAbilities) + if (removeAll + || (ab.isIntrinsic() && removeIntrinsic && !ab.isBasicLandAbility()) + || (ab.isAbility() && clearAbilities) || (ab.isSpell() && clearSpells)) { + ab.setTemporarilySuppressed(true); removedAbilities.add(ab); } } } - // Can't rmeove SAs in foreach loop that finds them - for (final SpellAbility ab : removedAbilities) { - c.removeSpellAbility(ab); - } - if (sa.hasParam("RemoveThisAbility") && !removedAbilities.contains(sa)) { c.removeSpellAbility(sa); removedAbilities.add(sa); @@ -215,20 +213,23 @@ public class AnimateEffect extends AnimateEffectBase { // suppress triggers from the animated card final List removedTriggers = Lists.newArrayList(); - if (sa.hasParam("OverwriteTriggers") || removeAll) { - final FCollectionView triggersToRemove = c.getTriggers(); - for (final Trigger trigger : triggersToRemove) { - trigger.setSuppressed(true); + if (sa.hasParam("OverwriteTriggers") || removeAll || removeIntrinsic) { + for (final Trigger trigger : c.getTriggers()) { + if (removeIntrinsic && !trigger.isIntrinsic()) { + continue; + } + trigger.setSuppressed(true); // why this not TemporarilySuppressed? removedTriggers.add(trigger); } } // give static abilities (should only be used by cards to give // itself a static ability) + final List addedStaticAbilities = Lists.newArrayList(); if (stAbs.size() > 0) { for (final String s : stAbs) { final String actualAbility = source.getSVar(s); - c.addStaticAbility(actualAbility); + addedStaticAbilities.add(c.addStaticAbility(actualAbility)); } } @@ -248,9 +249,11 @@ public class AnimateEffect extends AnimateEffectBase { // suppress static abilities from the animated card final List removedStatics = Lists.newArrayList(); - if (sa.hasParam("OverwriteStatics") || removeAll) { - final FCollectionView staticsToRemove = c.getStaticAbilities(); - for (final StaticAbility stAb : staticsToRemove) { + if (sa.hasParam("OverwriteStatics") || removeAll || removeIntrinsic) { + for (final StaticAbility stAb : c.getStaticAbilities()) { + if (removeIntrinsic && !stAb.isIntrinsic()) { + continue; + } stAb.setTemporarilySuppressed(true); removedStatics.add(stAb); } @@ -258,8 +261,11 @@ public class AnimateEffect extends AnimateEffectBase { // suppress static abilities from the animated card final List removedReplacements = Lists.newArrayList(); - if (sa.hasParam("OverwriteReplacements") || removeAll) { + if (sa.hasParam("OverwriteReplacements") || removeAll || removeIntrinsic) { for (final ReplacementEffect re : c.getReplacementEffects()) { + if (removeIntrinsic && !re.isIntrinsic()) { + continue; + } re.setTemporarilySuppressed(true); removedReplacements.add(re); } @@ -272,8 +278,6 @@ public class AnimateEffect extends AnimateEffectBase { } } - final boolean givesStAbs = (stAbs.size() > 0); - final GameCommand unanimate = new GameCommand() { private static final long serialVersionUID = -5861759814760561373L; @@ -281,9 +285,13 @@ public class AnimateEffect extends AnimateEffectBase { public void run() { doUnanimate(c, sa, finalDesc, hiddenKeywords, addedAbilities, addedTriggers, addedReplacements, - givesStAbs, removedAbilities, timestamp); + addedStaticAbilities, timestamp); game.fireEvent(new GameEventCardStatsChanged(c)); + + for (final SpellAbility sa : removedAbilities) { + sa.setTemporarilySuppressed(false); + } // give back suppressed triggers for (final Trigger t : removedTriggers) { t.setSuppressed(false); diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java index 627e5e6e84b..e6f814bb780 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java @@ -24,11 +24,10 @@ import forge.game.replacement.ReplacementEffect; import forge.game.spellability.SpellAbility; import forge.game.staticability.StaticAbility; import forge.game.trigger.Trigger; -import java.util.ArrayList; import java.util.List; public abstract class AnimateEffectBase extends SpellAbilityEffect { - void doAnimate(final Card c, final SpellAbility sa, final Integer power, final Integer toughness, + public static void doAnimate(final Card c, final SpellAbility sa, final Integer power, final Integer toughness, final CardType addType, final CardType removeType, final String colors, final List keywords, final List removeKeywords, final List hiddenKeywords, final long timestamp) { @@ -36,15 +35,19 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { boolean removeSuperTypes = false; boolean removeCardTypes = false; boolean removeSubTypes = false; + boolean removeLandTypes = false; boolean removeCreatureTypes = false; boolean removeArtifactTypes = false; + boolean removeEnchantmentTypes = false; if (sa.hasParam("OverwriteTypes")) { removeSuperTypes = true; removeCardTypes = true; removeSubTypes = true; + removeLandTypes = true; removeCreatureTypes = true; removeArtifactTypes = true; + removeEnchantmentTypes = true; } if (sa.hasParam("KeepSupertypes")) { @@ -57,6 +60,10 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { if (sa.hasParam("KeepSubtypes")) { removeSubTypes = false; + removeLandTypes = false; + removeCreatureTypes = false; + removeArtifactTypes = false; + removeEnchantmentTypes = false; } if (sa.hasParam("RemoveSuperTypes")) { @@ -71,23 +78,30 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { removeSubTypes = true; } + if (sa.hasParam("RemoveLandTypes")) { + removeCreatureTypes = true; + } if (sa.hasParam("RemoveCreatureTypes")) { removeCreatureTypes = true; } - if (sa.hasParam("RemoveArtifactTypes")) { removeArtifactTypes = true; } + if (sa.hasParam("RemoveEnchantmentTypes")) { + removeEnchantmentTypes = true; + } + if ((power != null) || (toughness != null)) { c.addNewPT(power, toughness, timestamp); } if (!addType.isEmpty() || !removeType.isEmpty() || removeCreatureTypes) { c.addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, - removeCreatureTypes, removeArtifactTypes, timestamp); + removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, timestamp); } - c.addChangedCardKeywords(keywords, removeKeywords, sa.hasParam("RemoveAllAbilities"), timestamp); + c.addChangedCardKeywords(keywords, removeKeywords, + sa.hasParam("RemoveAllAbilities"), sa.hasParam("RemoveIntrinsicAbilities"), timestamp); for (final String k : hiddenKeywords) { c.addHiddenExtrinsicKeyword(k); @@ -114,10 +128,10 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { * @param timestamp * a long. */ - void doUnanimate(final Card c, SpellAbility sa, final String colorDesc, + static void doUnanimate(final Card c, SpellAbility sa, final String colorDesc, final List hiddenKeywords, final List addedAbilities, final List addedTriggers, final List addedReplacements, - final boolean givesStAbs, final List removedAbilities, final long timestamp) { + final List addedStaticAbilities, final long timestamp) { if (sa.hasParam("LastsIndefinitely")) { return; @@ -127,16 +141,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { c.removeChangedCardKeywords(timestamp); - // remove all static abilities - if (givesStAbs) { - c.setStaticAbilities(new ArrayList()); - } - - if (sa.hasParam("Types") || sa.hasParam("RemoveTypes") - || sa.hasParam("RemoveCreatureTypes") || sa.hasParam("RemoveArtifactTypes")) { - c.removeChangedCardTypes(timestamp); - } - + c.removeChangedCardTypes(timestamp); c.removeColor(timestamp); for (final String k : hiddenKeywords) { @@ -147,10 +152,6 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { c.removeSpellAbility(saAdd); } - for (final SpellAbility saRem : removedAbilities) { - c.addSpellAbility(saRem); - } - for (final Trigger t : addedTriggers) { c.removeTrigger(t); } @@ -159,6 +160,10 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { c.removeReplacementEffect(rep); } + for (final StaticAbility stAb : addedStaticAbilities) { + c.removeStaticAbility(stAb); + } + // any other unanimate cleanup if (!c.isCreature()) { c.unEquipAllCards(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java index 72678bb72a6..b2f331aca7a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java @@ -350,7 +350,7 @@ public class CopyPermanentEffect extends SpellAbilityEffect { copyInPlay.setCloneOrigin(host); sa.getHostCard().addClone(copyInPlay); if (!pumpKeywords.isEmpty()) { - copyInPlay.addChangedCardKeywords(pumpKeywords, Lists.newArrayList(), false, timestamp); + copyInPlay.addChangedCardKeywords(pumpKeywords, Lists.newArrayList(), false, false, timestamp); } crds.add(copyInPlay); if (sa.hasParam("RememberCopied")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/DebuffEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DebuffEffect.java index 71256eab926..767f43bd9d8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DebuffEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DebuffEffect.java @@ -137,7 +137,7 @@ public class DebuffEffect extends SpellAbilityEffect { } removedKW.addAll(kws); - tgtC.addChangedCardKeywords(addedKW, removedKW, false, timestamp); + tgtC.addChangedCardKeywords(addedKW, removedKW, false, false, timestamp); } if (!sa.hasParam("Permanent")) { game.getEndOfTurn().addUntil(new GameCommand() { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java index a0a29b16aea..2a09ba0eb5b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ProtectAllEffect.java @@ -90,7 +90,7 @@ public class ProtectAllEffect extends SpellAbilityEffect { for (final Card tgtC : list) { if (tgtC.isInPlay()) { - tgtC.addChangedCardKeywords(gainsKWList, ImmutableList.of(), false, timestamp, true); + tgtC.addChangedCardKeywords(gainsKWList, null, false, false, timestamp, true); if (!sa.hasParam("Permanent")) { // If not Permanent, remove protection at EOT diff --git a/forge-game/src/main/java/forge/game/ability/effects/ProtectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ProtectEffect.java index 9ad893fd8be..3b2b1fe6445 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ProtectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ProtectEffect.java @@ -1,6 +1,5 @@ package forge.game.ability.effects; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import forge.GameCommand; import forge.card.MagicColor; @@ -153,7 +152,7 @@ public class ProtectEffect extends SpellAbilityEffect { continue; } - tgtC.addChangedCardKeywords(gainsKWList, ImmutableList.of(), false, timestamp, true); + tgtC.addChangedCardKeywords(gainsKWList, null, false, false, timestamp, true); if (!sa.hasParam("Permanent")) { // If not Permanent, remove protection at EOT @@ -181,7 +180,7 @@ public class ProtectEffect extends SpellAbilityEffect { continue; } - unTgtC.addChangedCardKeywords(gainsKWList, ImmutableList.of(), false, timestamp, true); + unTgtC.addChangedCardKeywords(gainsKWList, null, false, false, timestamp, true); if (!sa.hasParam("Permanent")) { // If not Permanent, remove protection at EOT diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java index 8a5d0dfebfb..e009bc3f718 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java @@ -13,10 +13,11 @@ import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.util.TextUtil; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import com.google.common.collect.Lists; + public class PumpAllEffect extends SpellAbilityEffect { private static void applyPumpAll(final SpellAbility sa, final List list, final int a, final int d, @@ -24,23 +25,18 @@ public class PumpAllEffect extends SpellAbilityEffect { final Game game = sa.getActivatingPlayer().getGame(); final long timestamp = game.getNextTimestamp(); - final List kws = new ArrayList(); - final List hiddenkws = new ArrayList(); - boolean suspend = false; + final List kws = Lists.newArrayList(); + final List hiddenkws = Lists.newArrayList(); for (String kw : keywords) { if (kw.startsWith("HIDDEN")) { hiddenkws.add(kw); } else { kws.add(kw); - if (kw.equals("Suspend")) { - suspend = true; - } } } for (final Card tgtC : list) { - // only pump things in the affected zones. boolean found = false; for (final ZoneType z : affectedZones) { @@ -55,7 +51,7 @@ public class PumpAllEffect extends SpellAbilityEffect { tgtC.addTempPowerBoost(a); tgtC.addTempToughnessBoost(d); - tgtC.addChangedCardKeywords(kws, new ArrayList(), false, timestamp); + tgtC.addChangedCardKeywords(kws, null, false, false, timestamp); for (String kw : hiddenkws) { tgtC.addHiddenExtrinsicKeyword(kw); @@ -118,13 +114,11 @@ public class PumpAllEffect extends SpellAbilityEffect { @Override public void resolve(final SpellAbility sa) { final List tgtPlayers = getTargetPlayers(sa); - final List affectedZones = new ArrayList(); + final List affectedZones = Lists.newArrayList(); final Game game = sa.getActivatingPlayer().getGame(); if (sa.hasParam("PumpZone")) { - for (final String zone : sa.getParam("PumpZone").split(",")) { - affectedZones.add(ZoneType.valueOf(zone)); - } + affectedZones.addAll(ZoneType.listValueOf(sa.getParam("PumpZone"))); } else { affectedZones.add(ZoneType.Battlefield); } @@ -149,7 +143,10 @@ public class PumpAllEffect extends SpellAbilityEffect { list = (CardCollection)AbilityUtils.filterListByType(list, valid, sa); - List keywords = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & ")) : new ArrayList(); + List keywords = Lists.newArrayList(); + if (sa.hasParam("KW")) { + keywords.addAll(Arrays.asList(sa.getParam("KW").split(" & "))); + } final int a = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumAtt"), sa, true); final int d = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumDef"), sa, true); diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java index cbbccffafe2..ad44066b83d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java @@ -52,7 +52,7 @@ public class PumpEffect extends SpellAbilityEffect { applyTo.addTempPowerBoost(a); applyTo.addTempToughnessBoost(d); - applyTo.addChangedCardKeywords(kws, Lists.newArrayList(), false, timestamp); + applyTo.addChangedCardKeywords(kws, Lists.newArrayList(), false, false, timestamp); if (redrawPT) { applyTo.updatePowerToughnessForView(); } if (sa.hasParam("LeaveBattlefield")) { @@ -251,7 +251,7 @@ public class PumpEffect extends SpellAbilityEffect { final String landtype = sa.getParam("DefinedLandwalk"); final Card c = AbilityUtils.getDefinedCards(host, landtype, sa).get(0); for (String type : c.getType()) { - if (CardType.isALandType(type) || CardType.isABasicLandType(type)) { + if (CardType.isALandType(type)) { keywords.add(type + "walk"); } } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 4bf199ef40b..0974bec1015 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -117,7 +117,7 @@ public class Card extends GameEntity implements Comparable { // changes by AF animate and continuous static effects - timestamp is the key of maps private final Map changedCardTypes = Maps.newTreeMap(); private final Map changedCardKeywords = Maps.newTreeMap(); - private final SortedMap changedCardColors = Maps.newTreeMap(); + private final Map changedCardColors = Maps.newTreeMap(); // changes that say "replace each instance of one [color,type] by another - timestamp is the key of maps private final CardChangedWords changedTextColors = new CardChangedWords(); @@ -2776,17 +2776,22 @@ public class Card extends GameEntity implements Comparable { public final void addChangedCardTypes(final CardType addType, final CardType removeType, final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes, - final boolean removeCreatureTypes, final boolean removeArtifactTypes, final long timestamp) { - addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, removeCreatureTypes, removeArtifactTypes, timestamp, true); + final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes, + final boolean removeEnchantmentTypes, + final long timestamp) { + addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, removeLandTypes, + removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, timestamp, true); } public final void addChangedCardTypes(final CardType addType, final CardType removeType, final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes, - final boolean removeCreatureTypes, final boolean removeArtifactTypes, final long timestamp, final boolean updateView) { + final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes, + final boolean removeEnchantmentTypes, + final long timestamp, final boolean updateView) { changedCardTypes.put(timestamp, new CardChangedType( addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, - removeCreatureTypes, removeArtifactTypes)); + removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes)); if (updateView) { currentState.getView().updateType(currentState); } @@ -2794,13 +2799,19 @@ public class Card extends GameEntity implements Comparable { public final void addChangedCardTypes(final String[] types, final String[] removeTypes, final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes, - final boolean removeCreatureTypes, final boolean removeArtifactTypes, final long timestamp) { - addChangedCardTypes(types, removeTypes, removeSuperTypes, removeCardTypes, removeSubTypes, removeCreatureTypes, removeArtifactTypes, timestamp, true); + final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes, + final boolean removeEnchantmentTypes, + final long timestamp) { + addChangedCardTypes(types, removeTypes, removeSuperTypes, removeCardTypes, removeSubTypes, + removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, + timestamp, true); } public final void addChangedCardTypes(final String[] types, final String[] removeTypes, final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes, - final boolean removeCreatureTypes, final boolean removeArtifactTypes, final long timestamp, final boolean updateView) { + final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes, + final boolean removeEnchantmentTypes, + final long timestamp, final boolean updateView) { CardType addType = null; CardType removeType = null; if (types != null) { @@ -2812,7 +2823,8 @@ public class Card extends GameEntity implements Comparable { } addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, - removeCreatureTypes, removeArtifactTypes, timestamp, updateView); + removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, + timestamp, updateView); } public final void removeChangedCardTypes(final long timestamp) { @@ -3272,23 +3284,25 @@ public class Card extends GameEntity implements Comparable { } public final void addChangedCardKeywords(final List keywords, final List removeKeywords, - final boolean removeAllKeywords, final long timestamp) { - addChangedCardKeywords(keywords, removeKeywords, removeAllKeywords, timestamp, true); + final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp) { + addChangedCardKeywords(keywords, removeKeywords, removeAllKeywords, removeIntrinsicKeywords, timestamp, true); } public final void addChangedCardKeywords(final List keywords, final List removeKeywords, - final boolean removeAllKeywords, final long timestamp, final boolean updateView) { + final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp, final boolean updateView) { keywords.removeAll(getCantHaveOrGainKeyword()); // if the key already exists - merge entries final KeywordsChange cks = changedCardKeywords.get(timestamp); if (cks != null) { - final KeywordsChange newCks = cks.merge(keywords, removeKeywords, removeAllKeywords); + final KeywordsChange newCks = cks.merge(keywords, removeKeywords, + removeAllKeywords, removeIntrinsicKeywords); newCks.addKeywordsToCard(this); changedCardKeywords.put(timestamp, newCks); } else { - final KeywordsChange newCks = new KeywordsChange(keywords, removeKeywords, removeAllKeywords); + final KeywordsChange newCks = new KeywordsChange(keywords, removeKeywords, + removeAllKeywords, removeIntrinsicKeywords); newCks.addKeywordsToCard(this); changedCardKeywords.put(timestamp, newCks); } @@ -3298,20 +3312,24 @@ public class Card extends GameEntity implements Comparable { } } - public final void addChangedCardKeywordsInternal(final List keywords, final List removeKeywords, - final boolean removeAllKeywords, final long timestamp, final boolean updateView) { + public final void addChangedCardKeywordsInternal( + final List keywords, final List removeKeywords, + final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, + final long timestamp, final boolean updateView) { KeywordCollection list = new KeywordCollection(); list.insertAll(keywords); list.removeAll(getCantHaveOrGainKeyword()); // if the key already exists - merge entries final KeywordsChange cks = changedCardKeywords.get(timestamp); if (cks != null) { - final KeywordsChange newCks = cks.merge(keywords, removeKeywords, removeAllKeywords); + final KeywordsChange newCks = cks.merge(keywords, removeKeywords, + removeAllKeywords, removeIntrinsicKeywords); newCks.addKeywordsToCard(this); changedCardKeywords.put(timestamp, newCks); } else { - final KeywordsChange newCks = new KeywordsChange(keywords, removeKeywords, removeAllKeywords); + final KeywordsChange newCks = new KeywordsChange(keywords, removeKeywords, + removeAllKeywords, removeIntrinsicKeywords); newCks.addKeywordsToCard(this); changedCardKeywords.put(timestamp, newCks); } @@ -3322,7 +3340,7 @@ public class Card extends GameEntity implements Comparable { } public final void addChangedCardKeywords(final String[] keywords, final String[] removeKeywords, - final boolean removeAllKeywords, final long timestamp) { + final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp) { List keywordsList = Lists.newArrayList(); List removeKeywordsList = Lists.newArrayList(); if (keywords != null) { @@ -3333,7 +3351,8 @@ public class Card extends GameEntity implements Comparable { removeKeywordsList = Lists.newArrayList(Arrays.asList(removeKeywords)); } - addChangedCardKeywords(keywordsList, removeKeywordsList, removeAllKeywords, timestamp); + addChangedCardKeywords(keywordsList, removeKeywordsList, + removeAllKeywords, removeIntrinsicKeywords, timestamp); } public final KeywordsChange removeChangedCardKeywords(final long timestamp) { @@ -3360,8 +3379,17 @@ public class Card extends GameEntity implements Comparable { KeywordCollection keywords = new KeywordCollection(); //final List keywords = Lists.newArrayList(); - - keywords.insertAll(state.getIntrinsicKeywords()); + boolean removeIntrinsic = false; + for (final KeywordsChange ck : changedCardKeywords.values()) { + if (ck.isRemoveIntrinsicKeywords()) { + removeIntrinsic = true; + break; + } + } + + if (!removeIntrinsic) { + keywords.insertAll(state.getIntrinsicKeywords()); + } keywords.insertAll(extrinsicKeyword.getValues()); // see if keyword changes are in effect @@ -3435,7 +3463,8 @@ public class Card extends GameEntity implements Comparable { public final void addChangedTextTypeWord(final String originalWord, final String newWord, final Long timestamp) { changedTextTypes.add(timestamp, originalWord, newWord); if (getType().hasSubtype(originalWord)) { - addChangedCardTypes(CardType.parse(newWord), CardType.parse(originalWord), false, false, false, false, false, timestamp); + addChangedCardTypes(CardType.parse(newWord), CardType.parse(originalWord), + false, false, false, false, false, false, false, timestamp); } updateKeywordsChangedText(timestamp); updateChangedText(); @@ -3474,7 +3503,7 @@ public class Card extends GameEntity implements Comparable { keywordsGrantedByTextChanges.add(newKw); } } - addChangedCardKeywordsInternal(addKeywords, removeKeywords, false, timestamp, true); + addChangedCardKeywordsInternal(addKeywords, removeKeywords, false, false, timestamp, true); } private void updateKeywordsOnRemoveChangedText(final KeywordsChange k) { @@ -4738,8 +4767,10 @@ public class Card extends GameEntity implements Comparable { public final void animateBestow(final boolean updateView) { bestowTimestamp = getGame().getNextTimestamp(); addChangedCardTypes(new CardType(Collections.singletonList("Aura")), - new CardType(Collections.singletonList("Creature")), false, false, false, false, true, bestowTimestamp, updateView); - addChangedCardKeywords(Collections.singletonList("Enchant creature"), Lists.newArrayList(), false, bestowTimestamp, updateView); + new CardType(Collections.singletonList("Creature")), + false, false, false, false, false, false, true, bestowTimestamp, updateView); + addChangedCardKeywords(Collections.singletonList("Enchant creature"), Lists.newArrayList(), + false, false, bestowTimestamp, updateView); } public final void unanimateBestow() { diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 72f6c28a315..9cbf572afb8 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -79,6 +79,7 @@ public class CardFactoryUtil { " | SpellDescription$ Add {" + strcolor + "}."; SpellAbility sa = AbilityFactory.getAbility(abString, state); sa.setIntrinsic(true); // always intristic + sa.setBasicLandAbility(true); // to exclude it from other suspress effects return sa; } diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java b/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java index ff51ca12e27..292741c323c 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordsChange.java @@ -37,6 +37,7 @@ public class KeywordsChange { private final List removeKeywordInterfaces = Lists.newArrayList(); private final List removeKeywords = Lists.newArrayList(); private boolean removeAllKeywords; + private boolean removeIntrinsicKeywords; /** * @@ -49,7 +50,8 @@ public class KeywordsChange { public KeywordsChange( final Iterable keywordList, final Collection removeKeywordList, - final boolean removeAll) { + final boolean removeAll, + final boolean removeIntrinsic) { if (keywordList != null) { this.keywords.addAll(keywordList); } @@ -59,12 +61,14 @@ public class KeywordsChange { } this.removeAllKeywords = removeAll; + this.removeIntrinsicKeywords = removeIntrinsic; } public KeywordsChange( final Collection keywordList, final Collection removeKeywordInterfaces, - final boolean removeAll) { + final boolean removeAll, + final boolean removeIntrinsic) { if (keywordList != null) { this.keywords.insertAll(keywordList); } @@ -74,6 +78,7 @@ public class KeywordsChange { } this.removeAllKeywords = removeAll; + this.removeIntrinsicKeywords = removeIntrinsic; } /** @@ -109,6 +114,10 @@ public class KeywordsChange { return this.removeAllKeywords; } + public final boolean isRemoveIntrinsicKeywords() { + return this.removeIntrinsicKeywords; + } + /** * @return whether this KeywordsChange doesn't have any effect. */ @@ -135,8 +144,9 @@ public class KeywordsChange { public final KeywordsChange merge( final Collection keywordList, final Collection removeKeywordList, - final boolean removeAll) { - KeywordsChange result = new KeywordsChange(keywordList, removeKeywordList, removeAll); + final boolean removeAll, + final boolean removeIntrinsic) { + KeywordsChange result = new KeywordsChange(keywordList, removeKeywordList, removeAll, removeIntrinsic); result.__merge(this); return result; } @@ -144,8 +154,9 @@ public class KeywordsChange { public final KeywordsChange merge( final Iterable keywordList, final Collection removeKeywordList, - final boolean removeAll) { - KeywordsChange result = new KeywordsChange(keywordList, removeKeywordList, removeAll); + final boolean removeAll, + final boolean removeIntrinsic) { + KeywordsChange result = new KeywordsChange(keywordList, removeKeywordList, removeAll, removeIntrinsic); result.__merge(this); return result; } @@ -157,5 +168,8 @@ public class KeywordsChange { if (other.removeAllKeywords) { removeAllKeywords = true; } + if (other.removeIntrinsicKeywords) { + removeIntrinsicKeywords = true; + } } } diff --git a/forge-game/src/main/java/forge/game/mana/ManaPool.java b/forge-game/src/main/java/forge/game/mana/ManaPool.java index a5c1930239a..2d2de63d968 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaPool.java +++ b/forge-game/src/main/java/forge/game/mana/ManaPool.java @@ -246,7 +246,7 @@ public class ManaPool implements Iterable { && host.getType().hasStringType(mana.getManaAbility().getAddsKeywordsType())) { final long timestamp = sa.getHostCard().getGame().getNextTimestamp(); final List kws = Arrays.asList(mana.getAddedKeywords().split(" & ")); - host.addChangedCardKeywords(kws, new ArrayList(), false, timestamp); + host.addChangedCardKeywords(kws, null, false, false, timestamp); if (mana.addsKeywordsUntil()) { final GameCommand untilEOT = new GameCommand() { private static final long serialVersionUID = -8285169579025607693L; diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 685eb2f827b..fc3db4f65d1 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -986,12 +986,13 @@ public class Player extends GameEntity implements Comparable { final KeywordsChange cks = changedKeywords.get(timestamp); ; - changedKeywords.put(timestamp, cks.merge(addKeywords, removeKeywords, cks.isRemoveAllKeywords())); + changedKeywords.put(timestamp, cks.merge(addKeywords, removeKeywords, + cks.isRemoveAllKeywords(), cks.isRemoveIntrinsicKeywords())); updateKeywords(); return; } - changedKeywords.put(timestamp, new KeywordsChange(addKeywords, removeKeywords, false)); + changedKeywords.put(timestamp, new KeywordsChange(addKeywords, removeKeywords, false, false)); updateKeywords(); game.fireEvent(new GameEventPlayerStatsChanged(this)); } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 2118184f9cb..b03e6538b83 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -106,6 +106,8 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private boolean blessing = false; private Integer chapter = null; + private boolean basicLandAbility = false; + private SplitSide splitSide = null; enum SplitSide { LEFT, RIGHT }; private int totalManaSpent = 0; @@ -754,6 +756,13 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return flashBackAbility; } + public void setBasicLandAbility(final boolean basicLandAbility0) { + basicLandAbility = basicLandAbility0; + } + public boolean isBasicLandAbility() { + return basicLandAbility && isIntrinsic(); + } + /** * @return the aftermath */ diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index a1af6d78c2b..ca173f8171b 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -126,7 +126,9 @@ public class StaticAbility extends CardTraitBase implements Comparable addFullAbs = null; boolean removeAllAbilities = false; + boolean removeIntrinsicAbilities = false; boolean removeNonMana = false; boolean removeSuperTypes = false; boolean removeCardTypes = false; boolean removeSubTypes = false; + boolean removeLandTypes = false; boolean removeCreatureTypes = false; boolean removeArtifactTypes = false; + boolean removeEnchantmentTypes = false; List mayLookAt = null; List withFlash = null; @@ -253,6 +256,11 @@ public final class StaticAbilityContinuous { removeNonMana = true; } } + // do this in type layer too in case of blood moon + if ((layer == StaticAbilityLayer.ABILITIES1 || layer == StaticAbilityLayer.TYPE) + && params.containsKey("RemoveIntrinsicAbilities")) { + removeIntrinsicAbilities = true; + } if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddAbility")) { final String[] sVars = params.get("AddAbility").split(" & "); @@ -310,12 +318,18 @@ public final class StaticAbilityContinuous { removeSubTypes = true; } + if (params.containsKey("RemoveLandTypes")) { + removeLandTypes = true; + } if (params.containsKey("RemoveCreatureTypes")) { removeCreatureTypes = true; } if (params.containsKey("RemoveArtifactTypes")) { removeArtifactTypes = true; } + if (params.containsKey("RemoveEnchantmentTypes")) { + removeEnchantmentTypes = true; + } } if (layer == StaticAbilityLayer.COLOR) { @@ -604,7 +618,7 @@ public final class StaticAbilityContinuous { // add keywords // TODO regular keywords currently don't try to use keyword multiplier // (Although nothing uses it at this time) - if ((addKeywords != null) || (removeKeywords != null) || removeAllAbilities) { + if ((addKeywords != null) || (removeKeywords != null) || removeAllAbilities || removeIntrinsicAbilities) { String[] newKeywords = null; if (addKeywords != null) { newKeywords = Arrays.copyOf(addKeywords, addKeywords.length); @@ -622,7 +636,8 @@ public final class StaticAbilityContinuous { } } - affectedCard.addChangedCardKeywords(newKeywords, removeKeywords, removeAllAbilities, + affectedCard.addChangedCardKeywords(newKeywords, removeKeywords, + removeAllAbilities, removeIntrinsicAbilities, hostCard.getTimestamp()); } @@ -686,7 +701,8 @@ public final class StaticAbilityContinuous { // add Types if ((addTypes != null) || (removeTypes != null)) { affectedCard.addChangedCardTypes(addTypes, removeTypes, removeSuperTypes, removeCardTypes, - removeSubTypes, removeCreatureTypes, removeArtifactTypes, hostCard.getTimestamp()); + removeSubTypes, removeLandTypes, removeCreatureTypes, removeArtifactTypes, + removeEnchantmentTypes, hostCard.getTimestamp()); } // add colors @@ -731,28 +747,41 @@ public final class StaticAbilityContinuous { } // remove triggers - if ((layer == StaticAbilityLayer.ABILITIES2 && (params.containsKey("RemoveTriggers")) || removeAllAbilities)) { + if ((layer == StaticAbilityLayer.ABILITIES2 && (params.containsKey("RemoveTriggers")) + || removeAllAbilities || removeIntrinsicAbilities)) { for (final Trigger trigger : affectedCard.getTriggers()) { - trigger.setTemporarilySuppressed(true); + if (removeAllAbilities || (removeIntrinsicAbilities && trigger.isIntrinsic())) { + trigger.setTemporarilySuppressed(true); + } } } // remove activated and static abilities - if (removeAllAbilities) { + if (removeAllAbilities || removeIntrinsicAbilities) { if (removeNonMana) { // Blood Sun - for (final SpellAbility mana : affectedCard.getNonManaAbilities()) { - mana.setTemporarilySuppressed(true); + for (final SpellAbility mana : affectedCard.getNonManaAbilities()) { + if (removeAllAbilities + || (removeIntrinsicAbilities && mana.isIntrinsic() && !mana.isBasicLandAbility())) { + mana.setTemporarilySuppressed(true); + } } } else { for (final SpellAbility ab : affectedCard.getSpellAbilities()) { - ab.setTemporarilySuppressed(true); + if (removeAllAbilities + || (removeIntrinsicAbilities && ab.isIntrinsic() && !ab.isBasicLandAbility())) { + ab.setTemporarilySuppressed(true); + } } } for (final StaticAbility stA : affectedCard.getStaticAbilities()) { - stA.setTemporarilySuppressed(true); + if (removeAllAbilities || (removeIntrinsicAbilities && stA.isIntrinsic())) { + stA.setTemporarilySuppressed(true); + } } for (final ReplacementEffect rE : affectedCard.getReplacementEffects()) { - rE.setTemporarilySuppressed(true); + if (removeAllAbilities || (removeIntrinsicAbilities && rE.isIntrinsic())) { + rE.setTemporarilySuppressed(true); + } } }