mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
refactor Keywords using Chosen Values
This commit is contained in:
committed by
Michael Kamensky
parent
6c512dd451
commit
01bf10c719
@@ -276,6 +276,10 @@ public class StaticEffect {
|
|||||||
affectedCard.removeChangedCardKeywords(getTimestamp());
|
affectedCard.removeChangedCardKeywords(getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasParam("CantHaveKeyword")) {
|
||||||
|
affectedCard.removeCantHaveKeyword(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
if (addHiddenKeywords != null) {
|
if (addHiddenKeywords != null) {
|
||||||
for (final String k : addHiddenKeywords) {
|
for (final String k : addHiddenKeywords) {
|
||||||
affectedCard.removeHiddenExtrinsicKeyword(k);
|
affectedCard.removeHiddenExtrinsicKeyword(k);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ package forge.game.ability.effects;
|
|||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -101,6 +101,10 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
c.addChangedCardKeywords(keywords, removeKeywords,
|
c.addChangedCardKeywords(keywords, removeKeywords,
|
||||||
sa.hasParam("RemoveAllAbilities"), sa.hasParam("RemoveIntrinsicAbilities"), timestamp);
|
sa.hasParam("RemoveAllAbilities"), sa.hasParam("RemoveIntrinsicAbilities"), timestamp);
|
||||||
|
|
||||||
|
if (sa.hasParam("CantHaveKeyword")) {
|
||||||
|
c.addCantHaveKeyword(timestamp, Keyword.setValueOf(sa.getParam("CantHaveKeyword")));
|
||||||
|
}
|
||||||
|
|
||||||
for (final String k : hiddenKeywords) {
|
for (final String k : hiddenKeywords) {
|
||||||
c.addHiddenExtrinsicKeyword(k);
|
c.addHiddenExtrinsicKeyword(k);
|
||||||
}
|
}
|
||||||
@@ -138,6 +142,8 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
|
|
||||||
c.removeChangedCardTraits(timestamp);
|
c.removeChangedCardTraits(timestamp);
|
||||||
|
|
||||||
|
c.removeCantHaveKeyword(timestamp);
|
||||||
|
|
||||||
for (final String k : hiddenKeywords) {
|
for (final String k : hiddenKeywords) {
|
||||||
c.removeHiddenExtrinsicKeyword(k);
|
c.removeHiddenExtrinsicKeyword(k);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private final NavigableMap<Long, CardCloneStates> clonedStates = Maps.newTreeMap();
|
private final NavigableMap<Long, CardCloneStates> clonedStates = Maps.newTreeMap();
|
||||||
private final NavigableMap<Long, CardCloneStates> textChangeStates = Maps.newTreeMap();
|
private final NavigableMap<Long, CardCloneStates> textChangeStates = Maps.newTreeMap();
|
||||||
|
|
||||||
|
private final Multimap<Long, Keyword> cantHaveKeywords = MultimapBuilder.hashKeys().enumSetValues(Keyword.class).build();
|
||||||
|
|
||||||
private final Map<Long, Integer> canBlockAdditional = Maps.newTreeMap();
|
private final Map<Long, Integer> canBlockAdditional = Maps.newTreeMap();
|
||||||
private final Set<Long> canBlockAny = Sets.newHashSet();
|
private final Set<Long> canBlockAny = Sets.newHashSet();
|
||||||
|
|
||||||
@@ -232,8 +234,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private String originalText = "", text = "";
|
private String originalText = "", text = "";
|
||||||
private String chosenType = "";
|
private String chosenType = "";
|
||||||
private List<String> chosenColors;
|
private List<String> chosenColors;
|
||||||
private String namedCard = "";
|
private String chosenName = "";
|
||||||
private int chosenNumber;
|
private Integer chosenNumber;
|
||||||
private Player chosenPlayer;
|
private Player chosenPlayer;
|
||||||
private Direction chosenDirection = null;
|
private Direction chosenDirection = null;
|
||||||
private String chosenMode = "";
|
private String chosenMode = "";
|
||||||
@@ -1445,6 +1447,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return currentState.getManaCost();
|
return currentState.getManaCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean hasChosenPlayer() {
|
||||||
|
return chosenPlayer != null;
|
||||||
|
}
|
||||||
public final Player getChosenPlayer() {
|
public final Player getChosenPlayer() {
|
||||||
return chosenPlayer;
|
return chosenPlayer;
|
||||||
}
|
}
|
||||||
@@ -1454,7 +1459,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
view.updateChosenPlayer(this);
|
view.updateChosenPlayer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getChosenNumber() {
|
public final boolean hasChosenNumber() {
|
||||||
|
return chosenNumber != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Integer getChosenNumber() {
|
||||||
return chosenNumber;
|
return chosenNumber;
|
||||||
}
|
}
|
||||||
public final void setChosenNumber(final int i) {
|
public final void setChosenNumber(final int i) {
|
||||||
@@ -1472,6 +1481,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
public final String getChosenType() {
|
public final String getChosenType() {
|
||||||
return chosenType;
|
return chosenType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setChosenType(final String s) {
|
public final void setChosenType(final String s) {
|
||||||
chosenType = s;
|
chosenType = s;
|
||||||
view.updateChosenType(this);
|
view.updateChosenType(this);
|
||||||
@@ -1537,13 +1547,24 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
view.updateChosenMode(this);
|
view.updateChosenMode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasChosenName() {
|
||||||
|
return chosenName != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChosenName() {
|
||||||
|
return chosenName;
|
||||||
|
}
|
||||||
|
public final void setChosenName(final String s) {
|
||||||
|
chosenName = s;
|
||||||
|
view.updateNamedCard(this);
|
||||||
|
}
|
||||||
|
|
||||||
// used for cards like Meddling Mage...
|
// used for cards like Meddling Mage...
|
||||||
public final String getNamedCard() {
|
public final String getNamedCard() {
|
||||||
return namedCard;
|
return getChosenName();
|
||||||
}
|
}
|
||||||
public final void setNamedCard(final String s) {
|
public final void setNamedCard(final String s) {
|
||||||
namedCard = s;
|
setChosenName(s);
|
||||||
view.updateNamedCard(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean getDrawnThisTurn() {
|
public final boolean getDrawnThisTurn() {
|
||||||
@@ -3677,7 +3698,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
|
|
||||||
public final void addChangedCardKeywords(final List<String> keywords, final List<String> removeKeywords,
|
public final void addChangedCardKeywords(final List<String> keywords, final List<String> removeKeywords,
|
||||||
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, 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
|
// if the key already exists - merge entries
|
||||||
final KeywordsChange cks = changedCardKeywords.get(timestamp);
|
final KeywordsChange cks = changedCardKeywords.get(timestamp);
|
||||||
if (cks != null) {
|
if (cks != null) {
|
||||||
@@ -3706,7 +3726,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
final long timestamp, final boolean updateView) {
|
final long timestamp, final boolean updateView) {
|
||||||
KeywordCollection list = new KeywordCollection();
|
KeywordCollection list = new KeywordCollection();
|
||||||
list.insertAll(keywords);
|
list.insertAll(keywords);
|
||||||
list.removeAll(getCantHaveOrGainKeyword());
|
|
||||||
// if the key already exists - merge entries
|
// if the key already exists - merge entries
|
||||||
final KeywordsChange cks = changedCardKeywords.get(timestamp);
|
final KeywordsChange cks = changedCardKeywords.get(timestamp);
|
||||||
if (cks != null) {
|
if (cks != null) {
|
||||||
@@ -3727,22 +3746,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addChangedCardKeywords(final String[] keywords, final String[] removeKeywords,
|
|
||||||
final boolean removeAllKeywords, final boolean removeIntrinsicKeywords, final long timestamp) {
|
|
||||||
List<String> keywordsList = Lists.newArrayList();
|
|
||||||
List<String> removeKeywordsList = Lists.newArrayList();
|
|
||||||
if (keywords != null) {
|
|
||||||
keywordsList = Lists.newArrayList(Arrays.asList(keywords));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removeKeywords != null) {
|
|
||||||
removeKeywordsList = Lists.newArrayList(Arrays.asList(removeKeywords));
|
|
||||||
}
|
|
||||||
|
|
||||||
addChangedCardKeywords(keywordsList, removeKeywordsList,
|
|
||||||
removeAllKeywords, removeIntrinsicKeywords, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final KeywordsChange removeChangedCardKeywords(final long timestamp) {
|
public final KeywordsChange removeChangedCardKeywords(final long timestamp) {
|
||||||
return removeChangedCardKeywords(timestamp, true);
|
return removeChangedCardKeywords(timestamp, true);
|
||||||
}
|
}
|
||||||
@@ -3817,21 +3820,17 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove Can't have keywords
|
||||||
|
for (Keyword k : getCantHaveKeyword()) {
|
||||||
|
keywords.removeAll(k);
|
||||||
|
}
|
||||||
|
|
||||||
state.setCachedKeywords(keywords);
|
state.setCachedKeywords(keywords);
|
||||||
}
|
}
|
||||||
private void visitUnhiddenKeywords(CardState state, Visitor<KeywordInterface> visitor) {
|
private void visitUnhiddenKeywords(CardState state, Visitor<KeywordInterface> visitor) {
|
||||||
if (changedCardKeywords.isEmpty()) {
|
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
||||||
// Fast path that doesn't involve temp allocations.
|
if (!visitor.visit(kw)) {
|
||||||
for (KeywordInterface kw : state.getIntrinsicKeywords()) {
|
return;
|
||||||
if (!visitor.visit(kw)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
|
|
||||||
if (!visitor.visit(kw)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4035,14 +4034,32 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<String> getCantHaveOrGainKeyword() {
|
public void addCantHaveKeyword(Keyword keyword, Long timestamp) {
|
||||||
final List<String> cantGain = Lists.newArrayList();
|
cantHaveKeywords.put(timestamp, keyword);
|
||||||
for (String s : hiddenExtrinsicKeyword) {
|
getView().updateCantHaveKeyword(this);
|
||||||
if (s.contains("can't have or gain")) {
|
}
|
||||||
cantGain.add(s.split("can't have or gain ")[1]);
|
|
||||||
}
|
public void addCantHaveKeyword(Long timestamp, Iterable<Keyword> keywords) {
|
||||||
|
cantHaveKeywords.putAll(timestamp, keywords);
|
||||||
|
getView().updateCantHaveKeyword(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeCantHaveKeyword(Long timestamp) {
|
||||||
|
return removeCantHaveKeyword(timestamp, true);
|
||||||
|
}
|
||||||
|
public boolean removeCantHaveKeyword(Long timestamp, boolean updateView) {
|
||||||
|
boolean change = !cantHaveKeywords.removeAll(timestamp).isEmpty();
|
||||||
|
if (change && updateView) {
|
||||||
|
getView().updateCantHaveKeyword(this);
|
||||||
|
updateKeywords();
|
||||||
|
if (isToken())
|
||||||
|
game.fireEvent(new GameEventTokenStateUpdate(this));
|
||||||
}
|
}
|
||||||
return cantGain;
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Keyword> getCantHaveKeyword() {
|
||||||
|
return cantHaveKeywords.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setStaticAbilities(final List<StaticAbility> a) {
|
public final void setStaticAbilities(final List<StaticAbility> a) {
|
||||||
@@ -5403,34 +5420,33 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
final String[] kws = kw.split(":");
|
final String[] kws = kw.split(":");
|
||||||
String characteristic = kws[1];
|
String characteristic = kws[1];
|
||||||
|
|
||||||
// if colorlessDamage then it does only check damage color..
|
if (characteristic.startsWith("Player")) {
|
||||||
if (colorlessDamage) {
|
// TODO need to handle that better in CardProperty
|
||||||
if (characteristic.endsWith("White") || characteristic.endsWith("Blue")
|
if (source.getController().isValid(characteristic.split(","), getController(), this, null)) {
|
||||||
|| characteristic.endsWith("Black") || characteristic.endsWith("Red")
|
return true;
|
||||||
|| characteristic.endsWith("Green") || characteristic.endsWith("Colorless")
|
}
|
||||||
|| characteristic.endsWith("ChosenColor")) {
|
} else {
|
||||||
characteristic += "Source";
|
// if colorlessDamage then it does only check damage color..
|
||||||
|
if (colorlessDamage) {
|
||||||
|
if (characteristic.endsWith("White") || characteristic.endsWith("Blue")
|
||||||
|
|| characteristic.endsWith("Black") || characteristic.endsWith("Red")
|
||||||
|
|| characteristic.endsWith("Green") || characteristic.endsWith("Colorless")
|
||||||
|
|| characteristic.endsWith("ChosenColor")) {
|
||||||
|
characteristic += "Source";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final String[] characteristics = characteristic.split(",");
|
final String[] characteristics = characteristic.split(",");
|
||||||
final String exception = kws.length > 3 ? kws[3] : null; // check "This effect cannot remove sth"
|
final String exception = kws.length > 3 ? kws[3] : null; // check "This effect cannot remove sth"
|
||||||
if (source.isValid(characteristics, getController(), this, null)
|
if (source.isValid(characteristics, getController(), this, null)
|
||||||
&& (!checkSBA || exception == null || !source.isValid(exception, getController(), this, null))) {
|
&& (!checkSBA || exception == null || !source.isValid(exception, getController(), this, null))) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (kw.equals("Protection from colored spells")) {
|
} else if (kw.equals("Protection from colored spells")) {
|
||||||
if (source.isSpell() && !source.isColorless()) {
|
if (source.isSpell() && !source.isColorless()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (kw.equals("Protection from the chosen player")) {
|
|
||||||
if (source.getController().equals(chosenPlayer)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (kw.equals("Protection from each converted mana cost other than the chosen number")) {
|
|
||||||
if (source.getCMC() != chosenNumber) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (kw.startsWith("Protection from opponent of ")) {
|
} else if (kw.startsWith("Protection from opponent of ")) {
|
||||||
final String playerName = kw.substring("Protection from opponent of ".length());
|
final String playerName = kw.substring("Protection from opponent of ".length());
|
||||||
if (source.getController().isOpponentOf(playerName)) {
|
if (source.getController().isOpponentOf(playerName)) {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -72,7 +72,7 @@ import io.sentry.event.BreadcrumbBuilder;
|
|||||||
* <p>
|
* <p>
|
||||||
* CardFactoryUtil class.
|
* CardFactoryUtil class.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
@@ -92,7 +92,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* abilityMorphDown.
|
* abilityMorphDown.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param sourceCard
|
* @param sourceCard
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @return a {@link forge.game.spellability.SpellAbility} object.
|
* @return a {@link forge.game.spellability.SpellAbility} object.
|
||||||
@@ -134,7 +134,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* abilityMorphUp.
|
* abilityMorphUp.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param sourceCard
|
* @param sourceCard
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @return a {@link forge.game.spellability.AbilityActivated} object.
|
* @return a {@link forge.game.spellability.AbilityActivated} object.
|
||||||
@@ -223,7 +223,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* isTargetStillValid.
|
* isTargetStillValid.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param ability
|
* @param ability
|
||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
* a {@link forge.game.spellability.SpellAbility} object.
|
||||||
* @param target
|
* @param target
|
||||||
@@ -268,7 +268,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* hasProtectionFrom.
|
* hasProtectionFrom.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param card
|
* @param card
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @param target
|
* @param target
|
||||||
@@ -287,7 +287,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* isCounterable.
|
* isCounterable.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
@@ -300,7 +300,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* isCounterableBy.
|
* isCounterableBy.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @param sa
|
* @param sa
|
||||||
@@ -328,7 +328,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* countOccurrences.
|
* countOccurrences.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param arg1
|
* @param arg1
|
||||||
* a {@link java.lang.String} object.
|
* a {@link java.lang.String} object.
|
||||||
* @param arg2
|
* @param arg2
|
||||||
@@ -349,7 +349,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* parseMath.
|
* parseMath.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param expression
|
* @param expression
|
||||||
* a {@link java.lang.String} object.
|
* a {@link java.lang.String} object.
|
||||||
* @return an array of {@link java.lang.String} objects.
|
* @return an array of {@link java.lang.String} objects.
|
||||||
@@ -363,7 +363,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* Parse player targeted X variables.
|
* Parse player targeted X variables.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param objects
|
* @param objects
|
||||||
* a {@link java.util.ArrayList} object.
|
* a {@link java.util.ArrayList} object.
|
||||||
* @param s
|
* @param s
|
||||||
@@ -395,7 +395,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* Parse player targeted X variables.
|
* Parse player targeted X variables.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param players
|
* @param players
|
||||||
* a {@link java.util.ArrayList} object.
|
* a {@link java.util.ArrayList} object.
|
||||||
* @param s
|
* @param s
|
||||||
@@ -518,9 +518,9 @@ public class CardFactoryUtil {
|
|||||||
public static int playerXProperty(final Player player, final String s, final Card source) {
|
public static int playerXProperty(final Player player, final String s, final Card source) {
|
||||||
final String[] l = s.split("/");
|
final String[] l = s.split("/");
|
||||||
final String m = extractOperators(s);
|
final String m = extractOperators(s);
|
||||||
|
|
||||||
final Game game = player.getGame();
|
final Game game = player.getGame();
|
||||||
|
|
||||||
// count valid cards in any specified zone/s
|
// count valid cards in any specified zone/s
|
||||||
if (l[0].startsWith("Valid") && !l[0].contains("Valid ")) {
|
if (l[0].startsWith("Valid") && !l[0].contains("Valid ")) {
|
||||||
String[] lparts = l[0].split(" ", 2);
|
String[] lparts = l[0].split(" ", 2);
|
||||||
@@ -619,7 +619,7 @@ public class CardFactoryUtil {
|
|||||||
if (value.contains("CardsDrawn")) {
|
if (value.contains("CardsDrawn")) {
|
||||||
return doXMath(player.getNumDrawnThisTurn(), m, source);
|
return doXMath(player.getNumDrawnThisTurn(), m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.contains("CardsDiscardedThisTurn")) {
|
if (value.contains("CardsDiscardedThisTurn")) {
|
||||||
return doXMath(player.getNumDiscardedThisTurn(), m, source);
|
return doXMath(player.getNumDiscardedThisTurn(), m, source);
|
||||||
}
|
}
|
||||||
@@ -643,7 +643,7 @@ public class CardFactoryUtil {
|
|||||||
if (value.equals("OpponentsAttackedThisTurn")) {
|
if (value.equals("OpponentsAttackedThisTurn")) {
|
||||||
return doXMath(player.getAttackedOpponentsThisTurn().size(), m, source);
|
return doXMath(player.getAttackedOpponentsThisTurn().size(), m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
return doXMath(0, m, source);
|
return doXMath(0, m, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +651,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* Parse non-mana X variables.
|
* Parse non-mana X variables.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @param expression
|
* @param expression
|
||||||
@@ -677,7 +677,8 @@ public class CardFactoryUtil {
|
|||||||
if (l[0].startsWith("Number$")) {
|
if (l[0].startsWith("Number$")) {
|
||||||
final String number = l[0].substring(7);
|
final String number = l[0].substring(7);
|
||||||
if (number.equals("ChosenNumber")) {
|
if (number.equals("ChosenNumber")) {
|
||||||
return doXMath(c.getChosenNumber(), m, c);
|
int x = c.getChosenNumber() == null ? 0 : c.getChosenNumber();
|
||||||
|
return doXMath(x, m, c);
|
||||||
}
|
}
|
||||||
return doXMath(Integer.parseInt(number), m, c);
|
return doXMath(Integer.parseInt(number), m, c);
|
||||||
}
|
}
|
||||||
@@ -708,7 +709,7 @@ public class CardFactoryUtil {
|
|||||||
String[] lparts = l[0].split(" ", 2);
|
String[] lparts = l[0].split(" ", 2);
|
||||||
final String[] rest = lparts[1].split(",");
|
final String[] rest = lparts[1].split(",");
|
||||||
|
|
||||||
final CardCollectionView cardsInZones = lparts[0].length() > 5
|
final CardCollectionView cardsInZones = lparts[0].length() > 5
|
||||||
? game.getCardsIn(ZoneType.listValueOf(lparts[0].substring(5)))
|
? game.getCardsIn(ZoneType.listValueOf(lparts[0].substring(5)))
|
||||||
: game.getCardsIn(ZoneType.Battlefield);
|
: game.getCardsIn(ZoneType.Battlefield);
|
||||||
|
|
||||||
@@ -764,7 +765,7 @@ public class CardFactoryUtil {
|
|||||||
String[] lparts = l[0].split(" ", 2);
|
String[] lparts = l[0].split(" ", 2);
|
||||||
final String[] rest = lparts[1].split(",");
|
final String[] rest = lparts[1].split(",");
|
||||||
|
|
||||||
final CardCollectionView cardsInZones = lparts[0].length() > 12
|
final CardCollectionView cardsInZones = lparts[0].length() > 12
|
||||||
? game.getCardsIn(ZoneType.listValueOf(lparts[0].substring(12)))
|
? game.getCardsIn(ZoneType.listValueOf(lparts[0].substring(12)))
|
||||||
: game.getCardsIn(ZoneType.Battlefield);
|
: game.getCardsIn(ZoneType.Battlefield);
|
||||||
|
|
||||||
@@ -950,7 +951,7 @@ public class CardFactoryUtil {
|
|||||||
if (sq[0].equals("RegeneratedThisTurn")) {
|
if (sq[0].equals("RegeneratedThisTurn")) {
|
||||||
return doXMath(c.getRegeneratedThisTurn(), m, c);
|
return doXMath(c.getRegeneratedThisTurn(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TriggeringObjects
|
// TriggeringObjects
|
||||||
if (sq[0].startsWith("Triggered")) {
|
if (sq[0].startsWith("Triggered")) {
|
||||||
return doXMath(xCount((Card) c.getTriggeringObject(AbilityKey.Card), sq[0].substring(9)), m, c);
|
return doXMath(xCount((Card) c.getTriggeringObject(AbilityKey.Card), sq[0].substring(9)), m, c);
|
||||||
@@ -1045,7 +1046,7 @@ public class CardFactoryUtil {
|
|||||||
CardCollection filtered = CardLists.getValidCards(allSrc, restriction, cc, c);
|
CardCollection filtered = CardLists.getValidCards(allSrc, restriction, cc, c);
|
||||||
return doXMath(filtered.size(), m, c);
|
return doXMath(filtered.size(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("YourLandsPlayed")) {
|
if (sq[0].contains("YourLandsPlayed")) {
|
||||||
return doXMath(cc.getLandsPlayedThisTurn(), m, c);
|
return doXMath(cc.getLandsPlayedThisTurn(), m, c);
|
||||||
}
|
}
|
||||||
@@ -1056,7 +1057,7 @@ public class CardFactoryUtil {
|
|||||||
cc.getCardsIn(ZoneType.Library).getFirst().getCMC();
|
cc.getCardsIn(ZoneType.Library).getFirst().getCMC();
|
||||||
return doXMath(cmc, m, c);
|
return doXMath(cmc, m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count$EnchantedControllerCreatures
|
// Count$EnchantedControllerCreatures
|
||||||
if (sq[0].contains("EnchantedControllerCreatures")) {
|
if (sq[0].contains("EnchantedControllerCreatures")) {
|
||||||
if (c.getEnchantingCard() != null) {
|
if (c.getEnchantingCard() != null) {
|
||||||
@@ -1080,7 +1081,7 @@ public class CardFactoryUtil {
|
|||||||
byte colorCode = ManaAtom.fromName(sq[1]);
|
byte colorCode = ManaAtom.fromName(sq[1]);
|
||||||
for (Card c0 : cards) {
|
for (Card c0 : cards) {
|
||||||
for (ManaCostShard sh : c0.getManaCost()){
|
for (ManaCostShard sh : c0.getManaCost()){
|
||||||
if ((sh.getColorMask() & colorCode) != 0)
|
if ((sh.getColorMask() & colorCode) != 0)
|
||||||
colorOcurrencices++;
|
colorOcurrencices++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1192,7 +1193,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
// Count$wasCastFrom<Zone>.<true>.<false>
|
// Count$wasCastFrom<Zone>.<true>.<false>
|
||||||
if (sq[0].startsWith("wasCastFrom")) {
|
if (sq[0].startsWith("wasCastFrom")) {
|
||||||
boolean zonesMatch = c.getCastFrom() == ZoneType.smartValueOf(sq[0].substring(11));
|
boolean zonesMatch = c.getCastFrom() == ZoneType.smartValueOf(sq[0].substring(11));
|
||||||
return doXMath(Integer.parseInt(sq[zonesMatch ? 1 : 2]), m, c);
|
return doXMath(Integer.parseInt(sq[zonesMatch ? 1 : 2]), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1307,7 +1308,7 @@ public class CardFactoryUtil {
|
|||||||
// Count$ThisTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
|
// Count$ThisTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
|
||||||
if (sq[0].contains("ThisTurnEntered")) {
|
if (sq[0].contains("ThisTurnEntered")) {
|
||||||
final String[] workingCopy = l[0].split("_");
|
final String[] workingCopy = l[0].split("_");
|
||||||
|
|
||||||
ZoneType destination = ZoneType.smartValueOf(workingCopy[1]);
|
ZoneType destination = ZoneType.smartValueOf(workingCopy[1]);
|
||||||
final boolean hasFrom = workingCopy[2].equals("from");
|
final boolean hasFrom = workingCopy[2].equals("from");
|
||||||
ZoneType origin = hasFrom ? ZoneType.smartValueOf(workingCopy[3]) : null;
|
ZoneType origin = hasFrom ? ZoneType.smartValueOf(workingCopy[3]) : null;
|
||||||
@@ -1324,7 +1325,7 @@ public class CardFactoryUtil {
|
|||||||
// Count$LastTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
|
// Count$LastTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
|
||||||
if (sq[0].contains("LastTurnEntered")) {
|
if (sq[0].contains("LastTurnEntered")) {
|
||||||
final String[] workingCopy = l[0].split("_");
|
final String[] workingCopy = l[0].split("_");
|
||||||
|
|
||||||
ZoneType destination = ZoneType.smartValueOf(workingCopy[1]);
|
ZoneType destination = ZoneType.smartValueOf(workingCopy[1]);
|
||||||
final boolean hasFrom = workingCopy[2].equals("from");
|
final boolean hasFrom = workingCopy[2].equals("from");
|
||||||
ZoneType origin = hasFrom ? ZoneType.smartValueOf(workingCopy[3]) : null;
|
ZoneType origin = hasFrom ? ZoneType.smartValueOf(workingCopy[3]) : null;
|
||||||
@@ -1422,7 +1423,7 @@ public class CardFactoryUtil {
|
|||||||
// Sorry for the Singleton use, replace this once this function has game passed into it
|
// Sorry for the Singleton use, replace this once this function has game passed into it
|
||||||
return doXMath(game.getPhaseHandler().getTurn(), m, c);
|
return doXMath(game.getPhaseHandler().getTurn(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Count$Random.<Min>.<Max>
|
//Count$Random.<Min>.<Max>
|
||||||
if (sq[0].equals("Random")) {
|
if (sq[0].equals("Random")) {
|
||||||
int min = StringUtils.isNumeric(sq[1]) ? Integer.parseInt(sq[1]) : xCount(c, c.getSVar(sq[1]));
|
int min = StringUtils.isNumeric(sq[1]) ? Integer.parseInt(sq[1]) : xCount(c, c.getSVar(sq[1]));
|
||||||
@@ -1475,16 +1476,16 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
return doXMath(ColorSet.fromMask(mask).countColors(), m, c);
|
return doXMath(ColorSet.fromMask(mask).countColors(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count$CardMulticolor.<numMC>.<numNotMC>
|
// Count$CardMulticolor.<numMC>.<numNotMC>
|
||||||
if (sq[0].contains("CardMulticolor")) {
|
if (sq[0].contains("CardMulticolor")) {
|
||||||
final boolean isMulti = CardUtil.getColors(c).isMulticolor();
|
final boolean isMulti = CardUtil.getColors(c).isMulticolor();
|
||||||
return doXMath(Integer.parseInt(sq[isMulti ? 1 : 2]), m, c);
|
return doXMath(Integer.parseInt(sq[isMulti ? 1 : 2]), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complex counting methods
|
// Complex counting methods
|
||||||
CardCollectionView someCards = getCardListForXCount(c, cc, sq);
|
CardCollectionView someCards = getCardListForXCount(c, cc, sq);
|
||||||
|
|
||||||
// 1/10 - Count$MaxCMCYouCtrl
|
// 1/10 - Count$MaxCMCYouCtrl
|
||||||
if (sq[0].contains("MaxCMC")) {
|
if (sq[0].contains("MaxCMC")) {
|
||||||
int mmc = Aggregates.max(someCards, CardPredicates.Accessors.fnGetCmc);
|
int mmc = Aggregates.max(someCards, CardPredicates.Accessors.fnGetCmc);
|
||||||
@@ -1498,7 +1499,7 @@ public class CardFactoryUtil {
|
|||||||
final List<Player> opps = cc.getOpponents();
|
final List<Player> opps = cc.getOpponents();
|
||||||
CardCollection someCards = new CardCollection();
|
CardCollection someCards = new CardCollection();
|
||||||
final Game game = c.getGame();
|
final Game game = c.getGame();
|
||||||
|
|
||||||
// Generic Zone-based counting
|
// Generic Zone-based counting
|
||||||
// Count$QualityAndZones.Subquality
|
// Count$QualityAndZones.Subquality
|
||||||
|
|
||||||
@@ -1621,7 +1622,7 @@ public class CardFactoryUtil {
|
|||||||
someCards.addAll(controller.getCardsIn(ZoneType.Graveyard));
|
someCards.addAll(controller.getCardsIn(ZoneType.Graveyard));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter lists based on the specified quality
|
// filter lists based on the specified quality
|
||||||
|
|
||||||
// "Clerics you control" - Count$TypeYouCtrl.Cleric
|
// "Clerics you control" - Count$TypeYouCtrl.Cleric
|
||||||
@@ -1747,7 +1748,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* handlePaid.
|
* handlePaid.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param paidList
|
* @param paidList
|
||||||
* a {@link forge.game.card.CardCollectionView} object.
|
* a {@link forge.game.card.CardCollectionView} object.
|
||||||
* @param string
|
* @param string
|
||||||
@@ -1792,7 +1793,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (string.startsWith("Valid")) {
|
if (string.startsWith("Valid")) {
|
||||||
|
|
||||||
final String[] splitString = string.split("/", 2);
|
final String[] splitString = string.split("/", 2);
|
||||||
String valid = splitString[0].substring(6);
|
String valid = splitString[0].substring(6);
|
||||||
final CardCollection list = CardLists.getValidCards(paidList, valid, source.getController(), source);
|
final CardCollection list = CardLists.getValidCards(paidList, valid, source.getController(), source);
|
||||||
@@ -1823,7 +1824,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* isMostProminentColor.
|
* isMostProminentColor.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param list
|
* @param list
|
||||||
* a {@link Iterable<Card>} object.
|
* a {@link Iterable<Card>} object.
|
||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
@@ -1845,12 +1846,12 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
byte mask = 0;
|
byte mask = 0;
|
||||||
int nMax = -1;
|
int nMax = -1;
|
||||||
for (int i = 0; i < cntColors; i++) {
|
for (int i = 0; i < cntColors; i++) {
|
||||||
if (map[i] > nMax)
|
if (map[i] > nMax)
|
||||||
mask = MagicColor.WUBRG[i];
|
mask = MagicColor.WUBRG[i];
|
||||||
else if (map[i] == nMax)
|
else if (map[i] == nMax)
|
||||||
mask |= MagicColor.WUBRG[i];
|
mask |= MagicColor.WUBRG[i];
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
nMax = map[i];
|
nMax = map[i];
|
||||||
}
|
}
|
||||||
@@ -1861,7 +1862,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* SortColorsFromList.
|
* SortColorsFromList.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param list
|
* @param list
|
||||||
* a {@link forge.game.card.CardCollection} object.
|
* a {@link forge.game.card.CardCollection} object.
|
||||||
* @return a List.
|
* @return a List.
|
||||||
@@ -1888,7 +1889,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* getMostProminentColorsFromList.
|
* getMostProminentColorsFromList.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param list
|
* @param list
|
||||||
* a {@link forge.game.card.CardCollectionView} object.
|
* a {@link forge.game.card.CardCollectionView} object.
|
||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
@@ -1915,12 +1916,12 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
byte mask = 0;
|
byte mask = 0;
|
||||||
int nMax = -1;
|
int nMax = -1;
|
||||||
for (int i = 0; i < cntColors; i++) {
|
for (int i = 0; i < cntColors; i++) {
|
||||||
if (map[i] > nMax)
|
if (map[i] > nMax)
|
||||||
mask = colorRestrictions.get(i);
|
mask = colorRestrictions.get(i);
|
||||||
else if (map[i] == nMax)
|
else if (map[i] == nMax)
|
||||||
mask |= colorRestrictions.get(i);
|
mask |= colorRestrictions.get(i);
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
nMax = map[i];
|
nMax = map[i];
|
||||||
}
|
}
|
||||||
@@ -1931,7 +1932,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* getMostProminentCreatureType.
|
* getMostProminentCreatureType.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param list
|
* @param list
|
||||||
* a {@link forge.game.card.CardCollection} object.
|
* a {@link forge.game.card.CardCollection} object.
|
||||||
* @return an int.
|
* @return an int.
|
||||||
@@ -1970,7 +1971,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* sharedKeywords.
|
* sharedKeywords.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param kw
|
* @param kw
|
||||||
* a String arry.
|
* a String arry.
|
||||||
* @return a List<String>.
|
* @return a List<String>.
|
||||||
@@ -1980,35 +1981,37 @@ public class CardFactoryUtil {
|
|||||||
final List<String> filteredkw = Lists.newArrayList();
|
final List<String> filteredkw = Lists.newArrayList();
|
||||||
final Player p = host.getController();
|
final Player p = host.getController();
|
||||||
CardCollectionView cardlist = p.getGame().getCardsIn(zones);
|
CardCollectionView cardlist = p.getGame().getCardsIn(zones);
|
||||||
final List<String> landkw = Lists.newArrayList();
|
final Set<String> landkw = Sets.newHashSet();
|
||||||
final List<String> protectionkw = Lists.newArrayList();
|
final Set<String> protectionkw = Sets.newHashSet();
|
||||||
final List<String> hexproofkw = Lists.newArrayList();
|
final Set<String> protectionColorkw = Sets.newHashSet();
|
||||||
final List<String> allkw = Lists.newArrayList();
|
final Set<String> hexproofkw = Sets.newHashSet();
|
||||||
|
final Set<String> allkw = Sets.newHashSet();
|
||||||
|
|
||||||
|
|
||||||
for (Card c : CardLists.getValidCards(cardlist, restrictions, p, host, null)) {
|
for (Card c : CardLists.getValidCards(cardlist, restrictions, p, host, null)) {
|
||||||
for (KeywordInterface inst : c.getKeywords()) {
|
for (KeywordInterface inst : c.getKeywords()) {
|
||||||
final String k = inst.getOriginal();
|
final String k = inst.getOriginal();
|
||||||
if (k.endsWith("walk")) {
|
if (k.endsWith("walk")) {
|
||||||
if (!landkw.contains(k)) {
|
landkw.add(k);
|
||||||
landkw.add(k);
|
|
||||||
}
|
|
||||||
} else if (k.startsWith("Protection")) {
|
} else if (k.startsWith("Protection")) {
|
||||||
if (!protectionkw.contains(k)) {
|
protectionkw.add(k);
|
||||||
protectionkw.add(k);
|
for(byte col : MagicColor.WUBRG) {
|
||||||
|
final String colString = "Protection from " + MagicColor.toLongString(col).toLowerCase();
|
||||||
|
if (k.contains(colString)) {
|
||||||
|
protectionColorkw.add(colString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (k.startsWith("Hexproof")) {
|
} else if (k.startsWith("Hexproof")) {
|
||||||
if (!hexproofkw.contains(k)) {
|
hexproofkw.add(k);
|
||||||
hexproofkw.add(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!allkw.contains(k)) {
|
|
||||||
allkw.add(k);
|
|
||||||
}
|
}
|
||||||
|
allkw.add(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (String keyword : kw) {
|
for (String keyword : kw) {
|
||||||
if (keyword.equals("Protection")) {
|
if (keyword.equals("Protection")) {
|
||||||
filteredkw.addAll(protectionkw);
|
filteredkw.addAll(protectionkw);
|
||||||
|
} else if (keyword.equals("ProtectionColor")) {
|
||||||
|
filteredkw.addAll(protectionColorkw);
|
||||||
} else if (keyword.equals("Landwalk")) {
|
} else if (keyword.equals("Landwalk")) {
|
||||||
filteredkw.addAll(landkw);
|
filteredkw.addAll(landkw);
|
||||||
} else if (keyword.equals("Hexproof")) {
|
} else if (keyword.equals("Hexproof")) {
|
||||||
@@ -2032,7 +2035,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* getNeededXDamage.
|
* getNeededXDamage.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param ability
|
* @param ability
|
||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
* a {@link forge.game.spellability.SpellAbility} object.
|
||||||
* @return a int.
|
* @return a int.
|
||||||
@@ -2052,7 +2055,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the ability factory abilities.
|
* Adds the ability factory abilities.
|
||||||
*
|
*
|
||||||
* @param card
|
* @param card
|
||||||
* the card
|
* the card
|
||||||
*/
|
*/
|
||||||
@@ -2081,7 +2084,7 @@ public class CardFactoryUtil {
|
|||||||
* <p>
|
* <p>
|
||||||
* postFactoryKeywords.
|
* postFactoryKeywords.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param card
|
* @param card
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
*/
|
*/
|
||||||
@@ -2186,7 +2189,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
return re;
|
return re;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addTriggerAbility(final KeywordInterface inst, final Card card, final boolean intrinsic) {
|
public static void addTriggerAbility(final KeywordInterface inst, final Card card, final boolean intrinsic) {
|
||||||
String keyword = inst.getOriginal();
|
String keyword = inst.getOriginal();
|
||||||
|
|
||||||
@@ -2222,13 +2225,13 @@ public class CardFactoryUtil {
|
|||||||
} else if (keyword.startsWith("Annihilator")) {
|
} else if (keyword.startsWith("Annihilator")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String n = k[1];
|
final String n = k[1];
|
||||||
|
|
||||||
final String trig = "Mode$ Attacks | ValidCard$ Card.Self | "
|
final String trig = "Mode$ Attacks | ValidCard$ Card.Self | "
|
||||||
+ "TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ "
|
+ "TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ "
|
||||||
+ "Annihilator " + n + " (" + inst.getReminderText() + ")";
|
+ "Annihilator " + n + " (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
final String effect = "DB$ Sacrifice | Defined$ DefendingPlayer | SacValid$ Permanent | Amount$ " + k[1];
|
final String effect = "DB$ Sacrifice | Defined$ DefendingPlayer | SacValid$ Permanent | Amount$ " + k[1];
|
||||||
|
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(trig, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(trig, card, intrinsic);
|
||||||
trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card));
|
trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card));
|
||||||
|
|
||||||
@@ -2239,12 +2242,12 @@ public class CardFactoryUtil {
|
|||||||
final String trig = "Mode$ Always | TriggerZones$ Battlefield | Secondary$ True"
|
final String trig = "Mode$ Always | TriggerZones$ Battlefield | Secondary$ True"
|
||||||
+ " | Static$ True | Blessing$ False | IsPresent$ Permanent.YouCtrl | PresentCompare$ GE10 "
|
+ " | Static$ True | Blessing$ False | IsPresent$ Permanent.YouCtrl | PresentCompare$ GE10 "
|
||||||
+ " | TriggerDescription$ Ascend (" + inst.getReminderText() + ")";
|
+ " | TriggerDescription$ Ascend (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
final String effect = "DB$ Ascend | Defined$ You";
|
final String effect = "DB$ Ascend | Defined$ You";
|
||||||
|
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(trig, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(trig, card, intrinsic);
|
||||||
trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card));
|
trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card));
|
||||||
|
|
||||||
inst.addTrigger(trigger);
|
inst.addTrigger(trigger);
|
||||||
} else {
|
} else {
|
||||||
SpellAbility sa = card.getFirstSpellAbility();
|
SpellAbility sa = card.getFirstSpellAbility();
|
||||||
@@ -2283,7 +2286,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
final Trigger bushidoTrigger1 = TriggerHandler.parseTrigger(trigBlock, card, intrinsic);
|
final Trigger bushidoTrigger1 = TriggerHandler.parseTrigger(trigBlock, card, intrinsic);
|
||||||
final Trigger bushidoTrigger2 = TriggerHandler.parseTrigger(trigBlocked, card, intrinsic);
|
final Trigger bushidoTrigger2 = TriggerHandler.parseTrigger(trigBlocked, card, intrinsic);
|
||||||
|
|
||||||
bushidoTrigger1.setOverridingAbility(pump);
|
bushidoTrigger1.setOverridingAbility(pump);
|
||||||
bushidoTrigger2.setOverridingAbility(pump);
|
bushidoTrigger2.setOverridingAbility(pump);
|
||||||
|
|
||||||
@@ -2449,7 +2452,7 @@ public class CardFactoryUtil {
|
|||||||
+ "TriggerDescription$ Evolve (" + inst.getReminderText()+ ")";
|
+ "TriggerDescription$ Evolve (" + inst.getReminderText()+ ")";
|
||||||
final String effect = "DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | "
|
final String effect = "DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | "
|
||||||
+ "CounterNum$ 1 | Evolve$ True";
|
+ "CounterNum$ 1 | Evolve$ True";
|
||||||
|
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
||||||
trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card));
|
trigger.setOverridingAbility(AbilityFactory.getAbility(effect, card));
|
||||||
|
|
||||||
@@ -2529,7 +2532,7 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("FadingCleanup","DB$ Cleanup | ClearRemembered$ True");
|
card.setSVar("FadingCleanup","DB$ Cleanup | ClearRemembered$ True");
|
||||||
card.setSVar("FadingCheckSVar","Count$RememberedSize");
|
card.setSVar("FadingCheckSVar","Count$RememberedSize");
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(upkeepTrig, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(upkeepTrig, card, intrinsic);
|
||||||
|
|
||||||
inst.addTrigger(trigger);
|
inst.addTrigger(trigger);
|
||||||
} else if (keyword.equals("Flanking")) {
|
} else if (keyword.equals("Flanking")) {
|
||||||
final StringBuilder trigFlanking = new StringBuilder(
|
final StringBuilder trigFlanking = new StringBuilder(
|
||||||
@@ -2617,7 +2620,7 @@ public class CardFactoryUtil {
|
|||||||
final Trigger trigHauntRemoved = TriggerHandler.parseTrigger(sbHauntRemoved.toString(), card,
|
final Trigger trigHauntRemoved = TriggerHandler.parseTrigger(sbHauntRemoved.toString(), card,
|
||||||
intrinsic);
|
intrinsic);
|
||||||
trigHauntRemoved.setOverridingAbility(unhaunt);
|
trigHauntRemoved.setOverridingAbility(unhaunt);
|
||||||
|
|
||||||
triggers.add(trigHauntRemoved);
|
triggers.add(trigHauntRemoved);
|
||||||
|
|
||||||
// Fifth, add all triggers and abilities to the card.
|
// Fifth, add all triggers and abilities to the card.
|
||||||
@@ -2662,7 +2665,7 @@ public class CardFactoryUtil {
|
|||||||
sb.append("Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigHideawayDig");
|
sb.append("Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigHideawayDig");
|
||||||
sb.append("| Secondary$ True | TriggerDescription$ When CARDNAME enters the battlefield, ");
|
sb.append("| Secondary$ True | TriggerDescription$ When CARDNAME enters the battlefield, ");
|
||||||
sb.append("look at the top four cards of your library, exile one face down");
|
sb.append("look at the top four cards of your library, exile one face down");
|
||||||
sb.append(", then put the rest on the bottom of your library.");
|
sb.append(", then put the rest on the bottom of your library.");
|
||||||
final Trigger hideawayTrigger = TriggerHandler.parseTrigger(sb.toString(), card, intrinsic);
|
final Trigger hideawayTrigger = TriggerHandler.parseTrigger(sb.toString(), card, intrinsic);
|
||||||
triggers.add(hideawayTrigger);
|
triggers.add(hideawayTrigger);
|
||||||
card.setSVar("TrigHideawayDig", "DB$ Dig | Defined$ You | DigNum$ 4 | DestinationZone$ Exile | ExileFaceDown$ True | RememberChanged$ True | SubAbility$ DBHideawayEffect");
|
card.setSVar("TrigHideawayDig", "DB$ Dig | Defined$ You | DigNum$ 4 | DestinationZone$ Exile | ExileFaceDown$ True | RememberChanged$ True | SubAbility$ DBHideawayEffect");
|
||||||
@@ -2676,7 +2679,7 @@ public class CardFactoryUtil {
|
|||||||
triggers.add(changeZoneTrigger);
|
triggers.add(changeZoneTrigger);
|
||||||
card.setSVar("DBHideawayRemember", "DB$ Animate | Defined$ Imprinted | RememberObjects$ Remembered | Permanent$ True");
|
card.setSVar("DBHideawayRemember", "DB$ Animate | Defined$ Imprinted | RememberObjects$ Remembered | Permanent$ True");
|
||||||
card.setSVar("DBHideawayCleanup", "DB$ Cleanup | ClearRemembered$ True");
|
card.setSVar("DBHideawayCleanup", "DB$ Cleanup | ClearRemembered$ True");
|
||||||
|
|
||||||
for (final Trigger trigger : triggers) {
|
for (final Trigger trigger : triggers) {
|
||||||
inst.addTrigger(trigger);
|
inst.addTrigger(trigger);
|
||||||
}
|
}
|
||||||
@@ -2728,7 +2731,7 @@ public class CardFactoryUtil {
|
|||||||
"Play Madness " + ManaCostParser.parse(manacost) + " - " + card.getName();
|
"Play Madness " + ManaCostParser.parse(manacost) + " - " + card.getName();
|
||||||
|
|
||||||
final String playMadness = "AB$ Play | Cost$ 0 | Defined$ Self | PlayCost$ " + manacost +
|
final String playMadness = "AB$ Play | Cost$ 0 | Defined$ Self | PlayCost$ " + manacost +
|
||||||
" | ConditionDefined$ Self | ConditionPresent$ Card.StrictlySelf+inZoneExile" +
|
" | ConditionDefined$ Self | ConditionPresent$ Card.StrictlySelf+inZoneExile" +
|
||||||
" | Optional$ True | SubAbility$ DBWasNotPlayMadness | RememberPlayed$ True | Madness$ True";
|
" | Optional$ True | SubAbility$ DBWasNotPlayMadness | RememberPlayed$ True | Madness$ True";
|
||||||
final String moveToYard = "DB$ ChangeZone | Defined$ Self.StrictlySelf | Origin$ Exile | " +
|
final String moveToYard = "DB$ ChangeZone | Defined$ Self.StrictlySelf | Origin$ Exile | " +
|
||||||
"Destination$ Graveyard | TrackDiscarded$ True | ConditionDefined$ Remembered | ConditionPresent$" +
|
"Destination$ Graveyard | TrackDiscarded$ True | ConditionDefined$ Remembered | ConditionPresent$" +
|
||||||
@@ -2747,7 +2750,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
final String effect = "DB$ Pump | Defined$ TriggeredAttackerLKICopy | NumAtt$ MeleeX | NumDef$ MeleeX";
|
final String effect = "DB$ Pump | Defined$ TriggeredAttackerLKICopy | NumAtt$ MeleeX | NumDef$ MeleeX";
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
||||||
|
|
||||||
SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
sa.setSVar("MeleeX", "TriggeredPlayersDefenders$Amount");
|
sa.setSVar("MeleeX", "TriggeredPlayersDefenders$Amount");
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
@@ -2797,20 +2800,20 @@ public class CardFactoryUtil {
|
|||||||
} else if (keyword.startsWith("Modular")) {
|
} else if (keyword.startsWith("Modular")) {
|
||||||
final String abStr = "DB$ PutCounter | ValidTgts$ Artifact.Creature | " +
|
final String abStr = "DB$ PutCounter | ValidTgts$ Artifact.Creature | " +
|
||||||
"TgtPrompt$ Select target artifact creature | CounterType$ P1P1 | CounterNum$ ModularX";
|
"TgtPrompt$ Select target artifact creature | CounterType$ P1P1 | CounterNum$ ModularX";
|
||||||
|
|
||||||
String trigStr = "Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard" +
|
String trigStr = "Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard" +
|
||||||
" | OptionalDecider$ TriggeredCardController | TriggerController$ TriggeredCardController" +
|
" | OptionalDecider$ TriggeredCardController | TriggerController$ TriggeredCardController" +
|
||||||
" | Secondary$ True | TriggerDescription$ When CARDNAME dies, " +
|
" | Secondary$ True | TriggerDescription$ When CARDNAME dies, " +
|
||||||
"you may put a +1/+1 counter on target artifact creature for each +1/+1 counter on CARDNAME";
|
"you may put a +1/+1 counter on target artifact creature for each +1/+1 counter on CARDNAME";
|
||||||
|
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
||||||
|
|
||||||
SpellAbility ab = AbilityFactory.getAbility(abStr, card);
|
SpellAbility ab = AbilityFactory.getAbility(abStr, card);
|
||||||
|
|
||||||
ab.setSVar("ModularX", "TriggeredCard$CardCounters.P1P1");
|
ab.setSVar("ModularX", "TriggeredCard$CardCounters.P1P1");
|
||||||
|
|
||||||
trigger.setOverridingAbility(ab);
|
trigger.setOverridingAbility(ab);
|
||||||
|
|
||||||
inst.addTrigger(trigger);
|
inst.addTrigger(trigger);
|
||||||
} else if (keyword.equals("Myriad")) {
|
} else if (keyword.equals("Myriad")) {
|
||||||
final String actualTrigger = "Mode$ Attacks | ValidCard$ Card.Self | Execute$ "
|
final String actualTrigger = "Mode$ Attacks | ValidCard$ Card.Self | Execute$ "
|
||||||
@@ -2834,7 +2837,7 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("MyriadDelTrig", dbString2);
|
card.setSVar("MyriadDelTrig", dbString2);
|
||||||
card.setSVar("MyriadExile", dbString3);
|
card.setSVar("MyriadExile", dbString3);
|
||||||
card.setSVar("MyriadCleanup", dbString4);
|
card.setSVar("MyriadCleanup", dbString4);
|
||||||
|
|
||||||
inst.addTrigger(parsedTrigger);
|
inst.addTrigger(parsedTrigger);
|
||||||
} else if (keyword.startsWith("Partner:")) {
|
} else if (keyword.startsWith("Partner:")) {
|
||||||
// Partner With
|
// Partner With
|
||||||
@@ -2855,7 +2858,7 @@ public class CardFactoryUtil {
|
|||||||
inst.addTrigger(trigger);
|
inst.addTrigger(trigger);
|
||||||
} else if (keyword.equals("Persist")) {
|
} else if (keyword.equals("Persist")) {
|
||||||
final String trigStr = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | OncePerEffect$ True " +
|
final String trigStr = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | OncePerEffect$ True " +
|
||||||
" | ValidCard$ Card.Self+counters_EQ0_M1M1 | Secondary$ True" +
|
" | ValidCard$ Card.Self+counters_EQ0_M1M1 | Secondary$ True" +
|
||||||
" | TriggerDescription$ Persist (" + inst.getReminderText() + ")";
|
" | TriggerDescription$ Persist (" + inst.getReminderText() + ")";
|
||||||
final String effect = "DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ M1M1_1";
|
final String effect = "DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ M1M1_1";
|
||||||
|
|
||||||
@@ -2892,7 +2895,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
inst.addTrigger(parsedTrigger);
|
inst.addTrigger(parsedTrigger);
|
||||||
} else if (keyword.equals("Prowess")) {
|
} else if (keyword.equals("Prowess")) {
|
||||||
final String trigProwess = "Mode$ SpellCast | ValidCard$ Card.nonCreature"
|
final String trigProwess = "Mode$ SpellCast | ValidCard$ Card.nonCreature"
|
||||||
+ " | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | TriggerDescription$ "
|
+ " | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | TriggerDescription$ "
|
||||||
+ "Prowess (" + inst.getReminderText() + ")";
|
+ "Prowess (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
@@ -2978,30 +2981,30 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
final String actualTrigger = "Mode$ SpellCast | ValidCard$ Card.Self | OptionalDecider$ You | "
|
final String actualTrigger = "Mode$ SpellCast | ValidCard$ Card.Self | OptionalDecider$ You | "
|
||||||
+ " Secondary$ True | TriggerDescription$ Ripple " + num + " - CARDNAME";
|
+ " Secondary$ True | TriggerDescription$ Ripple " + num + " - CARDNAME";
|
||||||
|
|
||||||
final String abString = "DB$ Dig | NoMove$ True | DigNum$ " + num +
|
final String abString = "DB$ Dig | NoMove$ True | DigNum$ " + num +
|
||||||
" | Reveal$ True | RememberRevealed$ True";
|
" | Reveal$ True | RememberRevealed$ True";
|
||||||
|
|
||||||
final String dbCast = "DB$ Play | Valid$ Card.IsRemembered+sameName | " +
|
final String dbCast = "DB$ Play | Valid$ Card.IsRemembered+sameName | " +
|
||||||
"ValidZone$ Library | WithoutManaCost$ True | Optional$ True | " +
|
"ValidZone$ Library | WithoutManaCost$ True | Optional$ True | " +
|
||||||
"Amount$ All";
|
"Amount$ All";
|
||||||
|
|
||||||
final String toBottom = "DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered "
|
final String toBottom = "DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered "
|
||||||
+ "| Origin$ Library | Destination$ Library | LibraryPosition$ -1";
|
+ "| Origin$ Library | Destination$ Library | LibraryPosition$ -1";
|
||||||
|
|
||||||
final String cleanuptxt = "DB$ Cleanup | ClearRemembered$ True";
|
final String cleanuptxt = "DB$ Cleanup | ClearRemembered$ True";
|
||||||
|
|
||||||
SpellAbility sa = AbilityFactory.getAbility(abString, card);
|
SpellAbility sa = AbilityFactory.getAbility(abString, card);
|
||||||
AbilitySub saCast = (AbilitySub)AbilityFactory.getAbility(dbCast, card);
|
AbilitySub saCast = (AbilitySub)AbilityFactory.getAbility(dbCast, card);
|
||||||
AbilitySub saBottom = (AbilitySub)AbilityFactory.getAbility(toBottom, card);
|
AbilitySub saBottom = (AbilitySub)AbilityFactory.getAbility(toBottom, card);
|
||||||
AbilitySub saCleanup = (AbilitySub)AbilityFactory.getAbility(cleanuptxt, card);
|
AbilitySub saCleanup = (AbilitySub)AbilityFactory.getAbility(cleanuptxt, card);
|
||||||
|
|
||||||
saBottom.setSubAbility(saCleanup);
|
saBottom.setSubAbility(saCleanup);
|
||||||
saCast.setSubAbility(saBottom);
|
saCast.setSubAbility(saBottom);
|
||||||
sa.setSubAbility(saCast);
|
sa.setSubAbility(saCast);
|
||||||
|
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
|
|
||||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic);
|
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic);
|
||||||
parsedTrigger.setOverridingAbility(sa);
|
parsedTrigger.setOverridingAbility(sa);
|
||||||
|
|
||||||
@@ -3071,13 +3074,13 @@ public class CardFactoryUtil {
|
|||||||
} else if (keyword.equals("Storm")) {
|
} else if (keyword.equals("Storm")) {
|
||||||
final String actualTrigger = "Mode$ SpellCast | ValidCard$ Card.Self | Secondary$ True"
|
final String actualTrigger = "Mode$ SpellCast | ValidCard$ Card.Self | Secondary$ True"
|
||||||
+ "| TriggerDescription$ Storm (" + inst.getReminderText() + ")";
|
+ "| TriggerDescription$ Storm (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
String effect = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ StormCount";
|
String effect = "DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Amount$ StormCount";
|
||||||
|
|
||||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic);
|
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic);
|
||||||
|
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
|
|
||||||
sa.setSVar("StormCount", "TriggerCount$CurrentStormCount/Minus.1");
|
sa.setSVar("StormCount", "TriggerCount$CurrentStormCount/Minus.1");
|
||||||
|
|
||||||
parsedTrigger.setOverridingAbility(sa);
|
parsedTrigger.setOverridingAbility(sa);
|
||||||
@@ -3142,7 +3145,7 @@ public class CardFactoryUtil {
|
|||||||
inst.addTrigger(parsedTrigger);
|
inst.addTrigger(parsedTrigger);
|
||||||
} else if (keyword.equals("Undying")) {
|
} else if (keyword.equals("Undying")) {
|
||||||
final String trigStr = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | OncePerEffect$ True " +
|
final String trigStr = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | OncePerEffect$ True " +
|
||||||
" | Execute$ UndyingReturn | ValidCard$ Card.Self+counters_EQ0_P1P1 | TriggerZones$ Battlefield | Secondary$ True" +
|
" | Execute$ UndyingReturn | ValidCard$ Card.Self+counters_EQ0_P1P1 | TriggerZones$ Battlefield | Secondary$ True" +
|
||||||
" | TriggerDescription$ Undying (" + inst.getReminderText() + ")";
|
" | TriggerDescription$ Undying (" + inst.getReminderText() + ")";
|
||||||
final String effect = "DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ P1P1_1";
|
final String effect = "DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ P1P1_1";
|
||||||
|
|
||||||
@@ -3210,10 +3213,10 @@ public class CardFactoryUtil {
|
|||||||
String strTrig = "Mode$ SpellCast | ValidCard$ Card.Self | ValidSA$ Spell.MayPlaySource | Static$ True | Secondary$ True "
|
String strTrig = "Mode$ SpellCast | ValidCard$ Card.Self | ValidSA$ Spell.MayPlaySource | Static$ True | Secondary$ True "
|
||||||
+ " | TriggerDescription$ If you cast it any time a sorcery couldn't have been cast, "
|
+ " | TriggerDescription$ If you cast it any time a sorcery couldn't have been cast, "
|
||||||
+ " the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.";
|
+ " the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.";
|
||||||
|
|
||||||
final String strDelay = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Cleanup | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.";
|
final String strDelay = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Cleanup | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.";
|
||||||
final String strSac = "DB$ SacrificeAll | Defined$ Self";
|
final String strSac = "DB$ SacrificeAll | Defined$ Self";
|
||||||
|
|
||||||
SpellAbility saDelay = AbilityFactory.getAbility(strDelay, card);
|
SpellAbility saDelay = AbilityFactory.getAbility(strDelay, card);
|
||||||
saDelay.setAdditionalAbility("Execute", (AbilitySub) AbilityFactory.getAbility(strSac, card));
|
saDelay.setAdditionalAbility("Execute", (AbilitySub) AbilityFactory.getAbility(strSac, card));
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(strTrig, card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(strTrig, card, intrinsic);
|
||||||
@@ -3422,9 +3425,9 @@ public class CardFactoryUtil {
|
|||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final Cost cost = new Cost(k[1], false);
|
final Cost cost = new Cost(k[1], false);
|
||||||
sb.append( cost.isOnlyManaCost() ? " " : "—");
|
sb.append( cost.isOnlyManaCost() ? " " : "—");
|
||||||
|
|
||||||
sb.append(cost.toSimpleString());
|
sb.append(cost.toSimpleString());
|
||||||
|
|
||||||
if (!cost.isOnlyManaCost()) {
|
if (!cost.isOnlyManaCost()) {
|
||||||
sb.append(".");
|
sb.append(".");
|
||||||
}
|
}
|
||||||
@@ -3521,7 +3524,7 @@ public class CardFactoryUtil {
|
|||||||
+ " | Description$ Rebound (" + inst.getReminderText() + ")";
|
+ " | Description$ Rebound (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
String abExile = "DB$ ChangeZone | Defined$ Self | Origin$ Stack | Destination$ Exile";
|
String abExile = "DB$ ChangeZone | Defined$ Self | Origin$ Stack | Destination$ Exile";
|
||||||
String delTrig = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You " +
|
String delTrig = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You " +
|
||||||
" | OptionalDecider$ You | RememberObjects$ Self | TriggerDescription$"
|
" | OptionalDecider$ You | RememberObjects$ Self | TriggerDescription$"
|
||||||
+ " At the beginning of your next upkeep, you may cast " + card.toString() + " without paying its mana cost.";
|
+ " At the beginning of your next upkeep, you may cast " + card.toString() + " without paying its mana cost.";
|
||||||
// TODO add check for still in exile
|
// TODO add check for still in exile
|
||||||
@@ -3647,7 +3650,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
inst.addReplacement(re);
|
inst.addReplacement(re);
|
||||||
}
|
}
|
||||||
|
|
||||||
// extra part for the Damage Prevention keywords
|
// extra part for the Damage Prevention keywords
|
||||||
if (keyword.startsWith("Prevent all ")) {
|
if (keyword.startsWith("Prevent all ")) {
|
||||||
// TODO add intrinsic warning
|
// TODO add intrinsic warning
|
||||||
@@ -3689,10 +3692,10 @@ public class CardFactoryUtil {
|
|||||||
inst.addReplacement(re);
|
inst.addReplacement(re);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (keyword.startsWith("If CARDNAME would be put into a graveyard "
|
else if (keyword.startsWith("If CARDNAME would be put into a graveyard "
|
||||||
+ "from anywhere, reveal CARDNAME and shuffle it into its owner's library instead.")) {
|
+ "from anywhere, reveal CARDNAME and shuffle it into its owner's library instead.")) {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("Event$ Moved | Destination$ Graveyard | ValidCard$ Card.Self ");
|
StringBuilder sb = new StringBuilder("Event$ Moved | Destination$ Graveyard | ValidCard$ Card.Self ");
|
||||||
|
|
||||||
// to show it on Nexus
|
// to show it on Nexus
|
||||||
@@ -3713,10 +3716,10 @@ public class CardFactoryUtil {
|
|||||||
re.setLayer(ReplacementLayer.Other);
|
re.setLayer(ReplacementLayer.Other);
|
||||||
|
|
||||||
re.setOverridingAbility(sa);
|
re.setOverridingAbility(sa);
|
||||||
|
|
||||||
inst.addReplacement(re);
|
inst.addReplacement(re);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyword.equals("CARDNAME enters the battlefield tapped.") || keyword.equals("Hideaway")) {
|
if (keyword.equals("CARDNAME enters the battlefield tapped.") || keyword.equals("Hideaway")) {
|
||||||
String effect = "DB$ Tap | Defined$ Self | ETB$ True "
|
String effect = "DB$ Tap | Defined$ Self | ETB$ True "
|
||||||
+ " | SpellDescription$ CARDNAME enters the battlefield tapped.";
|
+ " | SpellDescription$ CARDNAME enters the battlefield tapped.";
|
||||||
@@ -3727,11 +3730,11 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
inst.addReplacement(re);
|
inst.addReplacement(re);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyword.startsWith("ETBReplacement")) {
|
if (keyword.startsWith("ETBReplacement")) {
|
||||||
String[] splitkw = keyword.split(":");
|
String[] splitkw = keyword.split(":");
|
||||||
ReplacementLayer layer = ReplacementLayer.smartValueOf(splitkw[1]);
|
ReplacementLayer layer = ReplacementLayer.smartValueOf(splitkw[1]);
|
||||||
|
|
||||||
final boolean optional = splitkw.length >= 4 && splitkw[3].contains("Optional");
|
final boolean optional = splitkw.length >= 4 && splitkw[3].contains("Optional");
|
||||||
|
|
||||||
final String valid = splitkw.length >= 6 ? splitkw[5] : "Card.Self";
|
final String valid = splitkw.length >= 6 ? splitkw[5] : "Card.Self";
|
||||||
@@ -3765,7 +3768,7 @@ public class CardFactoryUtil {
|
|||||||
newSA.setIntrinsic(intrinsic);
|
newSA.setIntrinsic(intrinsic);
|
||||||
|
|
||||||
inst.addSpellAbility(newSA);
|
inst.addSpellAbility(newSA);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (keyword.startsWith("Adapt")) {
|
} else if (keyword.startsWith("Adapt")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
@@ -3838,7 +3841,7 @@ public class CardFactoryUtil {
|
|||||||
inst.addSpellAbility(awakenSpell);
|
inst.addSpellAbility(awakenSpell);
|
||||||
} else if (keyword.startsWith("Bestow")) {
|
} else if (keyword.startsWith("Bestow")) {
|
||||||
final String[] params = keyword.split(":");
|
final String[] params = keyword.split(":");
|
||||||
final String cost = params[1];
|
final String cost = params[1];
|
||||||
|
|
||||||
final StringBuilder sbAttach = new StringBuilder();
|
final StringBuilder sbAttach = new StringBuilder();
|
||||||
sbAttach.append("SP$ Attach | Cost$ ");
|
sbAttach.append("SP$ Attach | Cost$ ");
|
||||||
@@ -3892,10 +3895,10 @@ public class CardFactoryUtil {
|
|||||||
String costStr = kw[1];
|
String costStr = kw[1];
|
||||||
|
|
||||||
String effect = "AB$ CopyPermanent | Cost$ " + costStr + " ExileFromGrave<1/CARDNAME> " +
|
String effect = "AB$ CopyPermanent | Cost$ " + costStr + " ExileFromGrave<1/CARDNAME> " +
|
||||||
"| ActivationZone$ Graveyard | SorcerySpeed$ True | Embalm$ True " +
|
"| ActivationZone$ Graveyard | SorcerySpeed$ True | Embalm$ True " +
|
||||||
"| PrecostDesc$ Embalm | CostDesc$ " + ManaCostParser.parse(costStr) + " | Defined$ Self " +
|
"| PrecostDesc$ Embalm | CostDesc$ " + ManaCostParser.parse(costStr) + " | Defined$ Self " +
|
||||||
"| StackDescription$ Embalm - CARDNAME "+
|
"| StackDescription$ Embalm - CARDNAME "+
|
||||||
"| SpellDescription$ (" + inst.getReminderText() + ")" ;
|
"| SpellDescription$ (" + inst.getReminderText() + ")" ;
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
@@ -3957,7 +3960,7 @@ public class CardFactoryUtil {
|
|||||||
final String[] kw = keyword.split(":");
|
final String[] kw = keyword.split(":");
|
||||||
String costStr = kw[1];
|
String costStr = kw[1];
|
||||||
Cost cost = new Cost(costStr, true);
|
Cost cost = new Cost(costStr, true);
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append("AB$ CopyPermanent | Cost$ ").append(costStr).append(" ExileFromGrave<1/CARDNAME>")
|
sb.append("AB$ CopyPermanent | Cost$ ").append(costStr).append(" ExileFromGrave<1/CARDNAME>")
|
||||||
@@ -3978,7 +3981,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sb.append(" | StackDescription$ Eternalize - CARDNAME ")
|
sb.append(" | StackDescription$ Eternalize - CARDNAME ")
|
||||||
.append("| SpellDescription$ (").append(inst.getReminderText()).append(")");
|
.append("| SpellDescription$ (").append(inst.getReminderText()).append(")");
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(sb.toString(), card);
|
final SpellAbility sa = AbilityFactory.getAbility(sb.toString(), card);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
@@ -4018,7 +4021,7 @@ public class CardFactoryUtil {
|
|||||||
abilityStr.append("| CostDesc$ ").append(cost.toSimpleString()).append(" ");
|
abilityStr.append("| CostDesc$ ").append(cost.toSimpleString()).append(" ");
|
||||||
abilityStr.append("| SpellDescription$ (");
|
abilityStr.append("| SpellDescription$ (");
|
||||||
abilityStr.append(inst.getReminderText()).append(")");
|
abilityStr.append(inst.getReminderText()).append(")");
|
||||||
|
|
||||||
// instantiate attach ability
|
// instantiate attach ability
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card);
|
final SpellAbility sa = AbilityFactory.getAbility(abilityStr.toString(), card);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
@@ -4026,10 +4029,10 @@ public class CardFactoryUtil {
|
|||||||
final SpellAbility sa = AbilityFactory.buildFusedAbility(card);
|
final SpellAbility sa = AbilityFactory.buildFusedAbility(card);
|
||||||
card.addSpellAbility(sa);
|
card.addSpellAbility(sa);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
} else if (keyword.startsWith("Haunt")) {
|
} else if (keyword.startsWith("Haunt")) {
|
||||||
if (!card.isCreature() && intrinsic) {
|
if (!card.isCreature() && intrinsic) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String hauntSVarName = k[1];
|
final String hauntSVarName = k[1];
|
||||||
|
|
||||||
// no nice way to get the cost
|
// no nice way to get the cost
|
||||||
String abString = TextUtil.concatNoSpace(
|
String abString = TextUtil.concatNoSpace(
|
||||||
@@ -4062,9 +4065,9 @@ public class CardFactoryUtil {
|
|||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String magnitude = k[1];
|
final String magnitude = k[1];
|
||||||
final String manacost = k[2];
|
final String manacost = k[2];
|
||||||
|
|
||||||
final String reduceCost = k.length > 3 ? k[3] : null;
|
final String reduceCost = k.length > 3 ? k[3] : null;
|
||||||
|
|
||||||
Set<String> references = Sets.newHashSet();
|
Set<String> references = Sets.newHashSet();
|
||||||
String desc = "Monstrosity " + magnitude;
|
String desc = "Monstrosity " + magnitude;
|
||||||
|
|
||||||
@@ -4082,17 +4085,17 @@ public class CardFactoryUtil {
|
|||||||
if (!references.isEmpty()) {
|
if (!references.isEmpty()) {
|
||||||
effect += "| References$ " + TextUtil.join(references, ",");
|
effect += "| References$ " + TextUtil.join(references, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card.hasSVar("MonstrosityAILogic")) {
|
if (card.hasSVar("MonstrosityAILogic")) {
|
||||||
effect += "| AILogic$ " + card.getSVar("MonstrosityAILogic");
|
effect += "| AILogic$ " + card.getSVar("MonstrosityAILogic");
|
||||||
}
|
}
|
||||||
|
|
||||||
effect += "| SpellDescription$ " + desc + " (" + inst.getReminderText() + ")";
|
effect += "| SpellDescription$ " + desc + " (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
|
|
||||||
} else if (keyword.startsWith("Morph")) {
|
} else if (keyword.startsWith("Morph")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
|
|
||||||
@@ -4124,10 +4127,10 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String effect = "AB$ ChangeZone | Cost$ " + manacost +
|
String effect = "AB$ ChangeZone | Cost$ " + manacost +
|
||||||
" Return<1/Creature.attacking+unblocked/unblocked attacker> " +
|
" Return<1/Creature.attacking+unblocked/unblocked attacker> " +
|
||||||
"| PrecostDesc$ " + desc + " | CostDesc$ " + ManaCostParser.parse(manacost) +
|
"| PrecostDesc$ " + desc + " | CostDesc$ " + ManaCostParser.parse(manacost) +
|
||||||
"| ActivationZone$ Hand | Origin$ Hand | Ninjutsu$ True " +
|
"| ActivationZone$ Hand | Origin$ Hand | Ninjutsu$ True " +
|
||||||
"| Destination$ Battlefield | Defined$ Self " +
|
"| Destination$ Battlefield | Defined$ Self " +
|
||||||
"| SpellDescription$ (" + inst.getReminderText() + ")";
|
"| SpellDescription$ (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
@@ -4137,10 +4140,10 @@ public class CardFactoryUtil {
|
|||||||
// extra secondary effect for Commander Ninjutsu
|
// extra secondary effect for Commander Ninjutsu
|
||||||
if (commander) {
|
if (commander) {
|
||||||
effect = "AB$ ChangeZone | Cost$ " + manacost +
|
effect = "AB$ ChangeZone | Cost$ " + manacost +
|
||||||
" Return<1/Creature.attacking+unblocked/unblocked attacker> " +
|
" Return<1/Creature.attacking+unblocked/unblocked attacker> " +
|
||||||
"| PrecostDesc$ " + desc + " | CostDesc$ " + ManaCostParser.parse(manacost) +
|
"| PrecostDesc$ " + desc + " | CostDesc$ " + ManaCostParser.parse(manacost) +
|
||||||
"| ActivationZone$ Command | Origin$ Command | Ninjutsu$ True " +
|
"| ActivationZone$ Command | Origin$ Command | Ninjutsu$ True " +
|
||||||
"| Destination$ Battlefield | Defined$ Self | Secondary$ True " +
|
"| Destination$ Battlefield | Defined$ Self | Secondary$ True " +
|
||||||
"| SpellDescription$ (" + inst.getReminderText() + ")";
|
"| SpellDescription$ (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
sa = AbilityFactory.getAbility(effect, card);
|
sa = AbilityFactory.getAbility(effect, card);
|
||||||
@@ -4196,7 +4199,7 @@ public class CardFactoryUtil {
|
|||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String n = k[1];
|
final String n = k[1];
|
||||||
final String manacost = k[2];
|
final String manacost = k[2];
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("AB$ PutCounter | CounterType$ P1P1 | ActivationZone$ Hand");
|
sb.append("AB$ PutCounter | CounterType$ P1P1 | ActivationZone$ Hand");
|
||||||
sb.append("| ValidTgts$ Creature | TgtPrompt$ Select target creature");
|
sb.append("| ValidTgts$ Creature | TgtPrompt$ Select target creature");
|
||||||
@@ -4208,7 +4211,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(sb.toString(), card);
|
final SpellAbility sa = AbilityFactory.getAbility(sb.toString(), card);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
|
|
||||||
if (n.equals("X")) {
|
if (n.equals("X")) {
|
||||||
sa.setSVar("X", "Count$xPaid");
|
sa.setSVar("X", "Count$xPaid");
|
||||||
}
|
}
|
||||||
@@ -4220,7 +4223,7 @@ public class CardFactoryUtil {
|
|||||||
String effect = "AB$ PutCounter | Cost$ " + manacost + " ExileFromGrave<1/CARDNAME> " +
|
String effect = "AB$ PutCounter | Cost$ " + manacost + " ExileFromGrave<1/CARDNAME> " +
|
||||||
"| ActivationZone$ Graveyard | ValidTgts$ Creature | CounterType$ P1P1 " +
|
"| ActivationZone$ Graveyard | ValidTgts$ Creature | CounterType$ P1P1 " +
|
||||||
"| CounterNum$ ScavengeX | SorcerySpeed$ True " +
|
"| CounterNum$ ScavengeX | SorcerySpeed$ True " +
|
||||||
"| PrecostDesc$ Scavenge | CostDesc$ " + ManaCostParser.parse(manacost) +
|
"| PrecostDesc$ Scavenge | CostDesc$ " + ManaCostParser.parse(manacost) +
|
||||||
"| SpellDescription$ (" + inst.getReminderText() + ")";
|
"| SpellDescription$ (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
@@ -4252,10 +4255,10 @@ public class CardFactoryUtil {
|
|||||||
String desc = "Surge " + surgeCost.toSimpleString() + " (" + inst.getReminderText()
|
String desc = "Surge " + surgeCost.toSimpleString() + " (" + inst.getReminderText()
|
||||||
+ ")";
|
+ ")";
|
||||||
newSA.setDescription(desc);
|
newSA.setDescription(desc);
|
||||||
|
|
||||||
newSA.setIntrinsic(intrinsic);
|
newSA.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(newSA);
|
inst.addSpellAbility(newSA);
|
||||||
|
|
||||||
} else if (keyword.startsWith("Suspend") && !keyword.equals("Suspend")) {
|
} else if (keyword.startsWith("Suspend") && !keyword.equals("Suspend")) {
|
||||||
// only add it if suspend has counter and cost
|
// only add it if suspend has counter and cost
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
@@ -4285,7 +4288,7 @@ public class CardFactoryUtil {
|
|||||||
GameEntityCounterTable table = new GameEntityCounterTable();
|
GameEntityCounterTable table = new GameEntityCounterTable();
|
||||||
c.addCounter(CounterType.TIME, counters, getActivatingPlayer(), true, table);
|
c.addCounter(CounterType.TIME, counters, getActivatingPlayer(), true, table);
|
||||||
table.triggerCountersPutAll(game);
|
table.triggerCountersPutAll(game);
|
||||||
|
|
||||||
String sb = TextUtil.concatWithSpace(getActivatingPlayer().toString(),"has suspended", c.getName(), "with", String.valueOf(counters),"time counters on it.");
|
String sb = TextUtil.concatWithSpace(getActivatingPlayer().toString(),"has suspended", c.getName(), "with", String.valueOf(counters),"time counters on it.");
|
||||||
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
|
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
|
||||||
}
|
}
|
||||||
@@ -4342,11 +4345,11 @@ public class CardFactoryUtil {
|
|||||||
" | PrecostDesc$ Unearth | StackDescription$ " +
|
" | PrecostDesc$ Unearth | StackDescription$ " +
|
||||||
"Unearth: Return CARDNAME to the battlefield. | SpellDescription$" +
|
"Unearth: Return CARDNAME to the battlefield. | SpellDescription$" +
|
||||||
" (" + inst.getReminderText() + ")";
|
" (" + inst.getReminderText() + ")";
|
||||||
|
|
||||||
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
|
|
||||||
} else if (keyword.endsWith(" offering")) {
|
} else if (keyword.endsWith(" offering")) {
|
||||||
final String offeringType = keyword.split(" ")[0];
|
final String offeringType = keyword.split(" ")[0];
|
||||||
final SpellAbility sa = card.getFirstSpellAbility();
|
final SpellAbility sa = card.getFirstSpellAbility();
|
||||||
@@ -4363,7 +4366,7 @@ public class CardFactoryUtil {
|
|||||||
newSA.setDescription(sa.getDescription() + " (" + offeringType + " offering)");
|
newSA.setDescription(sa.getDescription() + " (" + offeringType + " offering)");
|
||||||
newSA.setIntrinsic(intrinsic);
|
newSA.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(newSA);
|
inst.addSpellAbility(newSA);
|
||||||
|
|
||||||
} else if (keyword.startsWith("Crew")) {
|
} else if (keyword.startsWith("Crew")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String power = k[1];
|
final String power = k[1];
|
||||||
@@ -4378,7 +4381,7 @@ public class CardFactoryUtil {
|
|||||||
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
final SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
|
|
||||||
} else if (keyword.startsWith("Cycling")) {
|
} else if (keyword.startsWith("Cycling")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
@@ -4396,7 +4399,7 @@ public class CardFactoryUtil {
|
|||||||
sa.setAlternativeCost(AlternativeCost.Cycling);
|
sa.setAlternativeCost(AlternativeCost.Cycling);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
|
|
||||||
} else if (keyword.startsWith("TypeCycling")) {
|
} else if (keyword.startsWith("TypeCycling")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String type = k[1];
|
final String type = k[1];
|
||||||
@@ -4420,7 +4423,7 @@ public class CardFactoryUtil {
|
|||||||
sa.setAlternativeCost(AlternativeCost.Cycling);
|
sa.setAlternativeCost(AlternativeCost.Cycling);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
inst.addSpellAbility(sa);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4551,7 +4554,7 @@ public class CardFactoryUtil {
|
|||||||
* @param card
|
* @param card
|
||||||
* @param altCost
|
* @param altCost
|
||||||
* @param sa
|
* @param sa
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static SpellAbility makeAltCostAbility(final Card card, final String altCost, final SpellAbility sa) {
|
private static SpellAbility makeAltCostAbility(final Card card, final String altCost, final SpellAbility sa) {
|
||||||
final Map<String, String> params = AbilityFactory.getMapParams(altCost);
|
final Map<String, String> params = AbilityFactory.getMapParams(altCost);
|
||||||
@@ -4569,9 +4572,9 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
altCostSA.setRestrictions(restriction);
|
altCostSA.setRestrictions(restriction);
|
||||||
|
|
||||||
final String costDescription = params.containsKey("Description") ? params.get("Description")
|
final String costDescription = params.containsKey("Description") ? params.get("Description")
|
||||||
: TextUtil.concatWithSpace("You may", abCost.toStringAlt(),"rather than pay", TextUtil.addSuffix(card.getName(),"'s mana cost."));
|
: TextUtil.concatWithSpace("You may", abCost.toStringAlt(),"rather than pay", TextUtil.addSuffix(card.getName(),"'s mana cost."));
|
||||||
|
|
||||||
altCostSA.setDescription(costDescription);
|
altCostSA.setDescription(costDescription);
|
||||||
if (params.containsKey("References")) {
|
if (params.containsKey("References")) {
|
||||||
for (String svar : params.get("References").split(",")) {
|
for (String svar : params.get("References").split(",")) {
|
||||||
|
|||||||
@@ -319,6 +319,14 @@ public final class CardUtil {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ColorSet getColorsYouCtrl(final Player p) {
|
||||||
|
byte b = 0;
|
||||||
|
for (Card c : p.getCardsIn(ZoneType.Battlefield)) {
|
||||||
|
b |= c.determineColor().getColor();
|
||||||
|
}
|
||||||
|
return ColorSet.fromMask(b);
|
||||||
|
}
|
||||||
|
|
||||||
public static CardState getFaceDownCharacteristic(Card c) {
|
public static CardState getFaceDownCharacteristic(Card c) {
|
||||||
final CardType type = new CardType();
|
final CardType type = new CardType();
|
||||||
type.add("Creature");
|
type.add("Creature");
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package forge.game.card;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import forge.ImageKeys;
|
import forge.ImageKeys;
|
||||||
import forge.card.*;
|
import forge.card.*;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
@@ -26,6 +28,7 @@ import java.util.EnumSet;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class CardView extends GameEntityView {
|
public class CardView extends GameEntityView {
|
||||||
private static final long serialVersionUID = -3624090829028979255L;
|
private static final long serialVersionUID = -3624090829028979255L;
|
||||||
@@ -422,6 +425,8 @@ public class CardView extends GameEntityView {
|
|||||||
case SchemeDeck:
|
case SchemeDeck:
|
||||||
// true for now, to actually see the Scheme cards (can't see deck anyway)
|
// true for now, to actually see the Scheme cards (can't see deck anyway)
|
||||||
return true;
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// special viewing permissions for viewer
|
// special viewing permissions for viewer
|
||||||
@@ -649,6 +654,17 @@ public class CardView extends GameEntityView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<String> cantHaveKeyword = this.getCantHaveKeyword();
|
||||||
|
if (cantHaveKeyword != null && !cantHaveKeyword.isEmpty()) {
|
||||||
|
sb.append("\r\n\r\n");
|
||||||
|
for(String k : cantHaveKeyword) {
|
||||||
|
sb.append("CARDNAME can't have or gain ".replaceAll("CARDNAME", getName()));
|
||||||
|
sb.append(k);
|
||||||
|
sb.append(".");
|
||||||
|
sb.append("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String cloner = get(TrackableProperty.Cloner);
|
String cloner = get(TrackableProperty.Cloner);
|
||||||
if (!cloner.isEmpty()) {
|
if (!cloner.isEmpty()) {
|
||||||
sb.append("\r\nCloned by: ").append(cloner);
|
sb.append("\r\nCloned by: ").append(cloner);
|
||||||
@@ -768,6 +784,18 @@ public class CardView extends GameEntityView {
|
|||||||
set(TrackableProperty.BlockAny, c.canBlockAny());
|
set(TrackableProperty.BlockAny, c.canBlockAny());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<String> getCantHaveKeyword() {
|
||||||
|
return get(TrackableProperty.CantHaveKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCantHaveKeyword(Card c) {
|
||||||
|
Set<String> keywords = Sets.newTreeSet();
|
||||||
|
for (Keyword k : c.getCantHaveKeyword()) {
|
||||||
|
keywords.add(k.toString());
|
||||||
|
}
|
||||||
|
set(TrackableProperty.CantHaveKeyword, keywords);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String name = getName();
|
String name = getName();
|
||||||
|
|||||||
@@ -287,4 +287,15 @@ public enum Keyword {
|
|||||||
|
|
||||||
return UNDEFINED;
|
return UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<Keyword> setValueOf(String value) {
|
||||||
|
Set<Keyword> result = EnumSet.noneOf(Keyword.class);
|
||||||
|
for (String s : value.split(" & ")) {
|
||||||
|
Keyword k = smartValueOf(s);
|
||||||
|
if (!UNDEFINED.equals(k)) {
|
||||||
|
result.add(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import forge.game.card.Card;
|
|||||||
|
|
||||||
public class KeywordCollection implements Iterable<String>, Serializable {
|
public class KeywordCollection implements Iterable<String>, Serializable {
|
||||||
private static final long serialVersionUID = -2882986558147844702L;
|
private static final long serialVersionUID = -2882986558147844702L;
|
||||||
|
|
||||||
private boolean hidden = false;
|
private boolean hidden = false;
|
||||||
|
|
||||||
private transient KeywordCollectionView view;
|
private transient KeywordCollectionView view;
|
||||||
@@ -64,7 +64,7 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAll(Iterable<String> keywords) {
|
public void addAll(Iterable<String> keywords) {
|
||||||
@@ -82,10 +82,10 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(String keyword) {
|
public boolean remove(String keyword) {
|
||||||
Iterator<KeywordInterface> it = map.values().iterator();
|
Iterator<KeywordInterface> it = map.values().iterator();
|
||||||
|
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
KeywordInterface k = it.next();
|
KeywordInterface k = it.next();
|
||||||
@@ -94,7 +94,7 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
|||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +102,10 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
|||||||
return map.remove(keyword.getKeyword(), keyword);
|
return map.remove(keyword.getKeyword(), keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean removeAll(Keyword kenum) {
|
||||||
|
return !map.removeAll(kenum).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean removeAll(Iterable<String> keywords) {
|
public boolean removeAll(Iterable<String> keywords) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
for (String k : keywords) {
|
for (String k : keywords) {
|
||||||
@@ -144,7 +148,7 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
|||||||
}
|
}
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<KeywordInterface> getValues() {
|
public Collection<KeywordInterface> getValues() {
|
||||||
return map.values();
|
return map.values();
|
||||||
}
|
}
|
||||||
@@ -163,7 +167,6 @@ public class KeywordCollection implements Iterable<String>, Serializable {
|
|||||||
public Iterator<String> iterator() {
|
public Iterator<String> iterator() {
|
||||||
return new Iterator<String>() {
|
return new Iterator<String>() {
|
||||||
private final Iterator<KeywordInterface> iterator = map.values().iterator();
|
private final Iterator<KeywordInterface> iterator = map.values().iterator();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ public class PlayerProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (property.startsWith("PlayerUID_")) {
|
||||||
|
if (player.getId() != Integer.parseInt(property.split("PlayerUID_")[1])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (property.equals("YourTeam")) {
|
} else if (property.equals("YourTeam")) {
|
||||||
if (!player.sameTeam(sourceController)) {
|
if (!player.sameTeam(sourceController)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -165,7 +165,8 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
|
|||||||
if (hasParam("AddKeyword") || hasParam("AddAbility")
|
if (hasParam("AddKeyword") || hasParam("AddAbility")
|
||||||
|| hasParam("AddTrigger") || hasParam("RemoveTriggers")
|
|| hasParam("AddTrigger") || hasParam("RemoveTriggers")
|
||||||
|| hasParam("RemoveKeyword") || hasParam("AddReplacementEffects")
|
|| hasParam("RemoveKeyword") || hasParam("AddReplacementEffects")
|
||||||
|| hasParam("AddStaticAbility") || hasParam("AddSVar")) {
|
|| hasParam("AddStaticAbility") || hasParam("AddSVar")
|
||||||
|
|| hasParam("CantHaveKeyword")) {
|
||||||
layers.add(StaticAbilityLayer.ABILITIES);
|
layers.add(StaticAbilityLayer.ABILITIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +182,6 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasParam("AddHiddenKeyword")) {
|
if (hasParam("AddHiddenKeyword")) {
|
||||||
// special rule for can't have or gain
|
|
||||||
if (getParam("AddHiddenKeyword").contains("can't have or gain")) {
|
|
||||||
layers.add(StaticAbilityLayer.ABILITIES);
|
|
||||||
}
|
|
||||||
layers.add(StaticAbilityLayer.RULES);
|
layers.add(StaticAbilityLayer.RULES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.staticability;
|
package forge.game.staticability;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
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.GameCommand;
|
import forge.GameCommand;
|
||||||
|
import forge.card.ColorSet;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
@@ -33,6 +35,7 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.replacement.ReplacementHandler;
|
import forge.game.replacement.ReplacementHandler;
|
||||||
@@ -113,9 +116,9 @@ public final class StaticAbilityContinuous {
|
|||||||
String setT = "";
|
String setT = "";
|
||||||
int setToughness = Integer.MAX_VALUE;
|
int setToughness = Integer.MAX_VALUE;
|
||||||
|
|
||||||
String[] addKeywords = null;
|
List<String> addKeywords = null;
|
||||||
List<String> addHiddenKeywords = Lists.newArrayList();
|
List<String> addHiddenKeywords = Lists.newArrayList();
|
||||||
String[] removeKeywords = null;
|
List<String> removeKeywords = null;
|
||||||
String[] addAbilities = null;
|
String[] addAbilities = null;
|
||||||
String[] addReplacements = null;
|
String[] addReplacements = null;
|
||||||
String[] addSVars = null;
|
String[] addSVars = null;
|
||||||
@@ -137,6 +140,8 @@ public final class StaticAbilityContinuous {
|
|||||||
|
|
||||||
boolean overwriteColors = false;
|
boolean overwriteColors = false;
|
||||||
|
|
||||||
|
Set<Keyword> cantHaveKeyword = null;
|
||||||
|
|
||||||
List<Player> mayLookAt = null;
|
List<Player> mayLookAt = null;
|
||||||
List<Player> withFlash = null;
|
List<Player> withFlash = null;
|
||||||
|
|
||||||
@@ -189,50 +194,96 @@ public final class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("AddKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("AddKeyword")) {
|
||||||
addKeywords = params.get("AddKeyword").split(" & ");
|
addKeywords = Lists.newArrayList(Arrays.asList(params.get("AddKeyword").split(" & ")));
|
||||||
final Iterable<String> chosencolors = hostCard.getChosenColors();
|
final List<String> newKeywords = Lists.newArrayList();
|
||||||
for (final String color : chosencolors) {
|
|
||||||
for (int w = 0; w < addKeywords.length; w++) {
|
// update keywords with Chosen parts
|
||||||
addKeywords[w] = addKeywords[w].replaceAll("ChosenColor", StringUtils.capitalize(color));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String chosenType = hostCard.getChosenType();
|
|
||||||
for (int w = 0; w < addKeywords.length; w++) {
|
|
||||||
addKeywords[w] = addKeywords[w].replaceAll("ChosenType", chosenType);
|
|
||||||
}
|
|
||||||
final String chosenName = hostCard.getNamedCard().replace(",", ";");
|
|
||||||
final String hostCardUID = Integer.toString(hostCard.getId()); // Protection with "doesn't remove" effect
|
final String hostCardUID = Integer.toString(hostCard.getId()); // Protection with "doesn't remove" effect
|
||||||
final String hostCardPower = Integer.toString(hostCard.getNetPower());
|
|
||||||
for (int w = 0; w < addKeywords.length; w++) {
|
final ColorSet colorsYouCtrl = CardUtil.getColorsYouCtrl(controller);
|
||||||
if (addKeywords[w].startsWith("Protection:")) {
|
|
||||||
String k = addKeywords[w];
|
Iterables.removeIf(addKeywords, new Predicate<String>() {
|
||||||
k = k.replaceAll("ChosenName", "Card.named" + chosenName);
|
@Override
|
||||||
k = k.replace("HostCardUID", hostCardUID);
|
public boolean apply(String input) {
|
||||||
addKeywords[w] = k;
|
if (!hostCard.hasChosenColor() && input.contains("ChosenColor")) {
|
||||||
} else if (addKeywords[w].startsWith("CantBeBlockedBy")) {
|
return true;
|
||||||
String k = addKeywords[w];
|
}
|
||||||
k = k.replaceAll("HostCardPower", hostCardPower);
|
if (!hostCard.hasChosenType() && input.contains("ChosenType")) {
|
||||||
addKeywords[w] = k;
|
return true;
|
||||||
|
}
|
||||||
|
if (!hostCard.hasChosenNumber() && input.contains("ChosenNumber")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!hostCard.hasChosenPlayer() && input.contains("ChosenPlayer")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!hostCard.hasChosenName() && input.contains("ChosenName")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// two variants for Red vs. red in keyword
|
||||||
|
if (input.contains("ColorsYouCtrl") || input.contains("colorsYouCtrl")) {
|
||||||
|
for (byte color : colorsYouCtrl) {
|
||||||
|
final String colorWord = MagicColor.toLongString(color);
|
||||||
|
String y = input.replaceAll("ColorsYouCtrl", StringUtils.capitalize(colorWord));
|
||||||
|
y = y.replaceAll("colorsYouCtrl", colorWord);
|
||||||
|
newKeywords.add(y);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
});
|
||||||
|
|
||||||
|
addKeywords.addAll(newKeywords);
|
||||||
|
|
||||||
|
addKeywords = Lists.transform(addKeywords, new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String input) {
|
||||||
|
if (hostCard.hasChosenColor()) {
|
||||||
|
input = input.replaceAll("ChosenColor", StringUtils.capitalize(hostCard.getChosenColor()));
|
||||||
|
}
|
||||||
|
if (hostCard.hasChosenType()) {
|
||||||
|
input = input.replaceAll("ChosenType", hostCard.getChosenType());
|
||||||
|
}
|
||||||
|
if (hostCard.hasChosenNumber()) {
|
||||||
|
input = input.replaceAll("ChosenNumber", String.valueOf(hostCard.getChosenNumber()));
|
||||||
|
}
|
||||||
|
if (hostCard.hasChosenPlayer()) {
|
||||||
|
Player cp = hostCard.getChosenPlayer();
|
||||||
|
input = input.replaceAll("ChosenPlayerUID", String.valueOf(cp.getId()));
|
||||||
|
input = input.replaceAll("ChosenPlayerName", cp.getName());
|
||||||
|
}
|
||||||
|
if (hostCard.hasChosenName()) {
|
||||||
|
final String chosenName = hostCard.getChosenName().replace(",", ";");
|
||||||
|
input = input.replaceAll("ChosenName", "Card.named" + chosenName);
|
||||||
|
}
|
||||||
|
input = input.replace("HostCardUID", hostCardUID);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
if (params.containsKey("SharedKeywordsZone")) {
|
if (params.containsKey("SharedKeywordsZone")) {
|
||||||
List<ZoneType> zones = ZoneType.listValueOf(params.get("SharedKeywordsZone"));
|
List<ZoneType> zones = ZoneType.listValueOf(params.get("SharedKeywordsZone"));
|
||||||
String[] restrictions = params.containsKey("SharedRestrictions") ? params.get("SharedRestrictions").split(",") : new String[] {"Card"};
|
String[] restrictions = params.containsKey("SharedRestrictions") ? params.get("SharedRestrictions").split(",") : new String[] {"Card"};
|
||||||
List<String> kw = CardFactoryUtil.sharedKeywords(Arrays.asList(addKeywords), restrictions, zones, hostCard);
|
addKeywords = CardFactoryUtil.sharedKeywords(addKeywords, restrictions, zones, hostCard);
|
||||||
addKeywords = kw.toArray(new String[kw.size()]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((layer == StaticAbilityLayer.RULES || layer == StaticAbilityLayer.ABILITIES) && params.containsKey("AddHiddenKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("CantHaveKeyword")) {
|
||||||
// can't have or gain, need to be applyed in ABILITIES1
|
cantHaveKeyword = Keyword.setValueOf(params.get("CantHaveKeyword"));
|
||||||
for (String k : params.get("AddHiddenKeyword").split(" & ")) {
|
}
|
||||||
if ( (k.contains("can't have or gain")) == (layer == StaticAbilityLayer.ABILITIES))
|
|
||||||
addHiddenKeywords.add(k);
|
if ((layer == StaticAbilityLayer.RULES) && params.containsKey("AddHiddenKeyword")) {
|
||||||
}
|
addHiddenKeywords.addAll(Arrays.asList(params.get("AddHiddenKeyword").split(" & ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("RemoveKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("RemoveKeyword")) {
|
||||||
removeKeywords = params.get("RemoveKeyword").split(" & ");
|
removeKeywords = Arrays.asList(params.get("RemoveKeyword").split(" & "));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("RemoveAllAbilities")) {
|
if (layer == StaticAbilityLayer.ABILITIES && params.containsKey("RemoveAllAbilities")) {
|
||||||
@@ -419,7 +470,7 @@ public final class StaticAbilityContinuous {
|
|||||||
|
|
||||||
// add keywords
|
// add keywords
|
||||||
if (addKeywords != null) {
|
if (addKeywords != null) {
|
||||||
p.addChangedKeywords(addKeywords, removeKeywords == null ? new String[0] : removeKeywords, se.getTimestamp());
|
p.addChangedKeywords(addKeywords, removeKeywords, se.getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
// add static abilities
|
// add static abilities
|
||||||
@@ -530,21 +581,44 @@ public final class StaticAbilityContinuous {
|
|||||||
// TODO regular keywords currently don't try to use keyword multiplier
|
// TODO regular keywords currently don't try to use keyword multiplier
|
||||||
// (Although nothing uses it at this time)
|
// (Although nothing uses it at this time)
|
||||||
if ((addKeywords != null) || (removeKeywords != null) || removeAllAbilities || removeIntrinsicAbilities) {
|
if ((addKeywords != null) || (removeKeywords != null) || removeAllAbilities || removeIntrinsicAbilities) {
|
||||||
String[] newKeywords = null;
|
List<String> newKeywords = null;
|
||||||
if (addKeywords != null) {
|
if (addKeywords != null) {
|
||||||
newKeywords = Arrays.copyOf(addKeywords, addKeywords.length);
|
newKeywords = Lists.newArrayList(addKeywords);
|
||||||
for (int j = 0; j < newKeywords.length; ++j) {
|
final List<String> extraKeywords = Lists.newArrayList();
|
||||||
if (newKeywords[j].contains("CardManaCost")) {
|
|
||||||
if (affectedCard.getManaCost().isNoCost()) {
|
Iterables.removeIf(newKeywords, new Predicate<String>() {
|
||||||
newKeywords[j] = ""; // prevent a crash (varolz the scar-striped + dryad arbor)
|
@Override
|
||||||
} else {
|
public boolean apply(String input) {
|
||||||
newKeywords[j] = newKeywords[j].replace("CardManaCost", affectedCard.getManaCost().getShortString());
|
if (input.contains("CardManaCost")) {
|
||||||
|
if (affectedCard.getManaCost().isNoCost()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (newKeywords[j].contains("ConvertedManaCost")) {
|
// replace one Keyword with list of keywords
|
||||||
final String costcmc = Integer.toString(affectedCard.getCMC());
|
if (input.startsWith("Protection") && input.contains("CardColors")) {
|
||||||
newKeywords[j] = newKeywords[j].replace("ConvertedManaCost", costcmc);
|
for (Byte color : affectedCard.determineColor()) {
|
||||||
|
extraKeywords.add(input.replace("CardColors", MagicColor.toLongString(color)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
newKeywords.addAll(extraKeywords);
|
||||||
|
|
||||||
|
newKeywords = Lists.transform(newKeywords, new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String input) {
|
||||||
|
if (input.contains("CardManaCost")) {
|
||||||
|
input = input.replace("CardManaCost", affectedCard.getManaCost().getShortString());
|
||||||
|
} else if (input.contains("ConvertedManaCost")) {
|
||||||
|
final String costcmc = Integer.toString(affectedCard.getCMC());
|
||||||
|
input = input.replace("ConvertedManaCost", costcmc);
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
affectedCard.addChangedCardKeywords(newKeywords, removeKeywords,
|
affectedCard.addChangedCardKeywords(newKeywords, removeKeywords,
|
||||||
@@ -682,6 +756,10 @@ public final class StaticAbilityContinuous {
|
|||||||
|| removeAllAbilities) {
|
|| removeAllAbilities) {
|
||||||
affectedCard.addChangedCardTraits(addedAbilities, null, addedTrigger, addedReplacementEffects, addedStaticAbility, removeAllAbilities, removeNonMana, false, hostCard.getTimestamp());
|
affectedCard.addChangedCardTraits(addedAbilities, null, addedTrigger, addedReplacementEffects, addedStaticAbility, removeAllAbilities, removeNonMana, false, hostCard.getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cantHaveKeyword != null) {
|
||||||
|
affectedCard.addCantHaveKeyword(hostCard.getTimestamp(), cantHaveKeyword);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer == StaticAbilityLayer.TYPE && removeIntrinsicAbilities) {
|
if (layer == StaticAbilityLayer.TYPE && removeIntrinsicAbilities) {
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ public enum TrackableProperty {
|
|||||||
NonAbilityText(TrackableTypes.StringType),
|
NonAbilityText(TrackableTypes.StringType),
|
||||||
FoilIndex(TrackableTypes.IntegerType),
|
FoilIndex(TrackableTypes.IntegerType),
|
||||||
|
|
||||||
|
CantHaveKeyword(TrackableTypes.StringListType),
|
||||||
|
|
||||||
//Player
|
//Player
|
||||||
IsAI(TrackableTypes.BooleanType),
|
IsAI(TrackableTypes.BooleanType),
|
||||||
LobbyPlayerName(TrackableTypes.StringType),
|
LobbyPlayerName(TrackableTypes.StringType),
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ Name:Arcane Lighthouse
|
|||||||
ManaCost:no cost
|
ManaCost:no cost
|
||||||
Types:Land
|
Types:Land
|
||||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||||
A:AB$ AnimateAll | Cost$ 1 T | ValidCards$ Creature.OppCtrl | RemoveKeywords$ Hexproof & Shroud | HiddenKeywords$ CARDNAME can't have or gain Hexproof & CARDNAME can't have or gain Shroud | SpellDescription$ Until end of turn, creatures your opponents control lose hexproof and shroud and can't have hexproof or shroud.
|
A:AB$ AnimateAll | Cost$ 1 T | ValidCards$ Creature.OppCtrl | RemoveKeywords$ Hexproof & Shroud | CantHaveKeyword$ Hexproof & Shroud | StackDescription$ SpellDescription | SpellDescription$ Until end of turn, creatures your opponents control lose hexproof and shroud and can't have hexproof or shroud.
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
Oracle:{T}: Add {C}.\n{1}, {T}: Until end of turn, creatures your opponents control lose hexproof and shroud and can't have hexproof or shroud.
|
Oracle:{T}: Add {C}.\n{1}, {T}: Until end of turn, creatures your opponents control lose hexproof and shroud and can't have hexproof or shroud.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:1 R R
|
|||||||
Types:Enchantment Creature Human Warrior
|
Types:Enchantment Creature Human Warrior
|
||||||
PT:3/2
|
PT:3/2
|
||||||
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Trample | Description$ Creatures you control have trample.
|
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Trample | Description$ Creatures you control have trample.
|
||||||
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Trample | AddHiddenKeyword$ CARDNAME can't have or gain Trample | Description$ Creatures your opponents control lose trample and can't have or gain trample.
|
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Trample | CantHaveKeyword$ Trample | Description$ Creatures your opponents control lose trample and can't have or gain trample.
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_aggression.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_aggression.jpg
|
||||||
Oracle:Creatures you control have trample.\nCreatures your opponents control lose trample and can't have or gain trample.
|
Oracle:Creatures you control have trample.\nCreatures your opponents control lose trample and can't have or gain trample.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:1 W W
|
|||||||
Types:Enchantment Creature Human Soldier
|
Types:Enchantment Creature Human Soldier
|
||||||
PT:2/2
|
PT:2/2
|
||||||
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ First Strike | Description$ Creatures you control have first strike.
|
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ First Strike | Description$ Creatures you control have first strike.
|
||||||
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ First Strike | AddHiddenKeyword$ CARDNAME can't have or gain First Strike | Description$ Creatures your opponents control lose first strike and can't have or gain first strike.
|
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ First Strike | CantHaveKeyword$ First Strike | Description$ Creatures your opponents control lose first strike and can't have or gain first strike.
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_courage.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_courage.jpg
|
||||||
Oracle:Creatures you control have first strike.\nCreatures your opponents control lose first strike and can't have or gain first strike.
|
Oracle:Creatures you control have first strike.\nCreatures your opponents control lose first strike and can't have or gain first strike.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:6 G G
|
|||||||
Types:Enchantment Creature Boar
|
Types:Enchantment Creature Boar
|
||||||
PT:6/5
|
PT:6/5
|
||||||
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Hexproof | Description$ Creatures you control have hexproof.
|
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Hexproof | Description$ Creatures you control have hexproof.
|
||||||
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Hexproof | AddHiddenKeyword$ CARDNAME can't have or gain Hexproof | Description$ Creatures your opponents control lose hexproof and can't have or gain hexproof.
|
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Hexproof | CantHaveKeyword$ Hexproof | Description$ Creatures your opponents control lose hexproof and can't have or gain hexproof.
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_endurance.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_endurance.jpg
|
||||||
Oracle:Creatures you control have hexproof.\nCreatures your opponents control lose hexproof and can't have or gain hexproof.
|
Oracle:Creatures you control have hexproof.\nCreatures your opponents control lose hexproof and can't have or gain hexproof.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:4 B B
|
|||||||
Types:Enchantment Creature Gorgon
|
Types:Enchantment Creature Gorgon
|
||||||
PT:2/3
|
PT:2/3
|
||||||
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Deathtouch | Description$ Creatures you control have deathtouch.
|
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Deathtouch | Description$ Creatures you control have deathtouch.
|
||||||
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Deathtouch | AddHiddenKeyword$ CARDNAME can't have or gain Deathtouch | Description$ Creatures your opponents control lose deathtouch and can't have or gain deathtouch.
|
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Deathtouch | CantHaveKeyword$ Deathtouch | Description$ Creatures your opponents control lose deathtouch and can't have or gain deathtouch.
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_finality.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_finality.jpg
|
||||||
Oracle:Creatures you control have deathtouch.\nCreatures your opponents control lose deathtouch and can't have or gain deathtouch.
|
Oracle:Creatures you control have deathtouch.\nCreatures your opponents control lose deathtouch and can't have or gain deathtouch.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:4 U U
|
|||||||
Types:Enchantment Creature Human Wizard
|
Types:Enchantment Creature Human Wizard
|
||||||
PT:3/2
|
PT:3/2
|
||||||
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Flying | Description$ Creatures you control have flying.
|
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddKeyword$ Flying | Description$ Creatures you control have flying.
|
||||||
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Flying | AddHiddenKeyword$ CARDNAME can't have or gain Flying | Description$ Creatures your opponents control lose flying and can't have or gain flying.
|
S:Mode$ Continuous | Affected$ Creature.OppCtrl | RemoveKeyword$ Flying | CantHaveKeyword$ Flying | Description$ Creatures your opponents control lose flying and can't have or gain flying.
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_imagination.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/archetype_of_imagination.jpg
|
||||||
Oracle:Creatures you control have flying.\nCreatures your opponents control lose flying and can't have or gain flying.
|
Oracle:Creatures you control have flying.\nCreatures your opponents control lose flying and can't have or gain flying.
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
Name:Earnest Fellowship
|
Name:Earnest Fellowship
|
||||||
ManaCost:1 W
|
ManaCost:1 W
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
Text:Each creature has protection from its colors.
|
S:Mode$ Continuous | Affected$ Creature | AddKeyword$ Protection from CardColors | Description$ Each creature has protection from its colors.
|
||||||
S:Mode$ Continuous | Affected$ Creature.White | AddKeyword$ Protection from white
|
|
||||||
S:Mode$ Continuous | Affected$ Creature.Blue | AddKeyword$ Protection from blue
|
|
||||||
S:Mode$ Continuous | Affected$ Creature.Black | AddKeyword$ Protection from black
|
|
||||||
S:Mode$ Continuous | Affected$ Creature.Red | AddKeyword$ Protection from red
|
|
||||||
S:Mode$ Continuous | Affected$ Creature.Green | AddKeyword$ Protection from green
|
|
||||||
SVar:NonStackingEffect:True
|
SVar:NonStackingEffect:True
|
||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
AI:RemoveDeck:Random
|
AI:RemoveDeck:Random
|
||||||
|
|||||||
@@ -2,15 +2,6 @@ Name:Empty-Shrine Kannushi
|
|||||||
ManaCost:W
|
ManaCost:W
|
||||||
Types:Creature Human Cleric
|
Types:Creature Human Cleric
|
||||||
PT:1/1
|
PT:1/1
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from white | CheckSVar$ WHITE | SVarCompare$ GE1 | Description$ CARDNAME has protection from the colors of permanents you control.
|
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from colorsYouCtrl | Description$ CARDNAME has protection from the colors of permanents you control.
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from blue | CheckSVar$ BLUE | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from black | CheckSVar$ BLACK | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from red | CheckSVar$ RED | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from green | CheckSVar$ GREEN | SVarCompare$ GE1
|
|
||||||
SVar:WHITE:Count$Valid Permanent.White+YouCtrl
|
|
||||||
SVar:BLUE:Count$Valid Permanent.Blue+YouCtrl
|
|
||||||
SVar:BLACK:Count$Valid Permanent.Black+YouCtrl
|
|
||||||
SVar:RED:Count$Valid Permanent.Red+YouCtrl
|
|
||||||
SVar:GREEN:Count$Valid Permanent.Green+YouCtrl
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/empty_shrine_kannushi.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/empty_shrine_kannushi.jpg
|
||||||
Oracle:Empty-Shrine Kannushi has protection from the colors of permanents you control.
|
Oracle:Empty-Shrine Kannushi has protection from the colors of permanents you control.
|
||||||
|
|||||||
@@ -2,21 +2,5 @@ Name:Escaped Shapeshifter
|
|||||||
ManaCost:3 U U
|
ManaCost:3 U U
|
||||||
Types:Creature Shapeshifter
|
Types:Creature Shapeshifter
|
||||||
PT:3/4
|
PT:3/4
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Flying | CheckSVar$ FLYING | SVarCompare$ GE1 | Description$ As long as an opponent controls a creature with flying not named CARDNAME, CARDNAME has flying. The same is true for first strike, trample, and protection from any color.
|
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Flying & First Strike & Trample & ProtectionColor | SharedKeywordsZone$ Battlefield | SharedRestrictions$ Creature.notnamed Escaped Shapeshifter+OppCtrl | Description$ As long as an opponent controls a creature with flying not named Escaped Shapeshifter, CARDNAME has flying. The same is true for first strike, trample, and protection from any color.
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ First Strike | CheckSVar$ FIRSTSTRIKE | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Trample | CheckSVar$ TRAMPLE | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from white | CheckSVar$ WHITE | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from blue | CheckSVar$ BLUE | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from black | CheckSVar$ BLACK | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from red | CheckSVar$ RED | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from green | CheckSVar$ GREEN | SVarCompare$ GE1
|
|
||||||
SVar:FLYING:Count$Valid Creature.withFlying+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:FIRSTSTRIKE:Count$Valid Creature.withFirst Strike+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:TRAMPLE:Count$Valid Creature.withTrample+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:WHITE:Count$Valid Creature.withProtection from white+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:BLUE:Count$Valid Creature.withProtection from blue+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:BLACK:Count$Valid Creature.withProtection from black+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:RED:Count$Valid Creature.withProtection from red+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:GREEN:Count$Valid Creature.withProtection from green+notnamed Escaped Shapeshifter+OppCtrl
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/escaped_shapeshifter.jpg
|
|
||||||
Oracle:As long as an opponent controls a creature with flying not named Escaped Shapeshifter, Escaped Shapeshifter has flying. The same is true for first strike, trample, and protection from any color.
|
Oracle:As long as an opponent controls a creature with flying not named Escaped Shapeshifter, Escaped Shapeshifter has flying. The same is true for first strike, trample, and protection from any color.
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ Types:Legendary Creature Human Warrior
|
|||||||
PT:6/1
|
PT:6/1
|
||||||
K:CARDNAME attacks each combat if able.
|
K:CARDNAME attacks each combat if able.
|
||||||
K:ETBReplacement:Other:ChooseNum
|
K:ETBReplacement:Other:ChooseNum
|
||||||
SVar:ChooseNum:DB$ ChooseNumber | Min$ 2 | Max$ 4 | Defined$ You | Random$ True
|
SVar:ChooseNum:DB$ ChooseNumber | Min$ 2 | Max$ 4 | Defined$ You | Random$ True | SpellDescription$ As Haktos enters the battlefield, choose 2, 3, or 4 at random.
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection from each converted mana cost other than the chosen number | Description$ CARDNAME has protection from each converted mana cost other than the chosen number.
|
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection:Card.cmcNEChosenNumber:Protection from each converted mana cost other than ChosenNumber | Description$ CARDNAME has protection from each converted mana cost other than the chosen number.
|
||||||
Oracle:Haktos the Unscarred attacks each combat if able.\nAs Haktos enters the battlefield, choose 2, 3, or 4 at random.\nHaktos has protection from each converted mana cost other than the chosen number.
|
Oracle:Haktos the Unscarred attacks each combat if able.\nAs Haktos enters the battlefield, choose 2, 3, or 4 at random.\nHaktos has protection from each converted mana cost other than the chosen number.
|
||||||
|
|||||||
@@ -3,15 +3,6 @@ ManaCost:1 W
|
|||||||
Types:Enchantment Aura
|
Types:Enchantment Aura
|
||||||
K:Enchant creature
|
K:Enchant creature
|
||||||
A:SP$ Attach | Cost$ 1 W | ValidTgts$ Creature | AILogic$ Pump
|
A:SP$ Attach | Cost$ 1 W | ValidTgts$ Creature | AILogic$ Pump
|
||||||
S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddKeyword$ Protection:Card.White:Protection from white:Card.CardUID_HostCardUID | CheckSVar$ WHITE | SVarCompare$ GE1 | Description$ Enchanted creature has protection from the colors of permanents you control. This effect doesn't remove CARDNAME.
|
S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddKeyword$ Protection:Card.ColorsYouCtrl:Protection from colorsYouCtrl:Card.CardUID_HostCardUID | Description$ Enchanted creature has protection from the colors of permanents you control. This effect doesn't remove CARDNAME.
|
||||||
S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddKeyword$ Protection:Card.Blue:Protection from blue:Card.CardUID_HostCardUID | CheckSVar$ BLUE | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddKeyword$ Protection:Card.Black:Protection from black:Card.CardUID_HostCardUID | CheckSVar$ BLACK | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddKeyword$ Protection:Card.Red:Protection from red:Card.CardUID_HostCardUID | CheckSVar$ RED | SVarCompare$ GE1
|
|
||||||
S:Mode$ Continuous | Affected$ Card.EnchantedBy | AddKeyword$ Protection:Card.Green:Protection from green:Card.CardUID_HostCardUID | CheckSVar$ GREEN | SVarCompare$ GE1
|
|
||||||
SVar:WHITE:Count$Valid Permanent.White+YouCtrl
|
|
||||||
SVar:BLUE:Count$Valid Permanent.Blue+YouCtrl
|
|
||||||
SVar:BLACK:Count$Valid Permanent.Black+YouCtrl
|
|
||||||
SVar:RED:Count$Valid Permanent.Red+YouCtrl
|
|
||||||
SVar:GREEN:Count$Valid Permanent.Green+YouCtrl
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/pledge_of_loyalty.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/pledge_of_loyalty.jpg
|
||||||
Oracle:Enchant creature\nEnchanted creature has protection from the colors of permanents you control. This effect doesn't remove Pledge of Loyalty.
|
Oracle:Enchant creature\nEnchanted creature has protection from the colors of permanents you control. This effect doesn't remove Pledge of Loyalty.
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ Types:Creature Merfolk Rogue
|
|||||||
PT:3/1
|
PT:3/1
|
||||||
K:ETBReplacement:Other:ChooseP
|
K:ETBReplacement:Other:ChooseP
|
||||||
SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Player | AILogic$ Curse | SpellDescription$ As CARDNAME enters the battlefield, choose a player.
|
SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Player | AILogic$ Curse | SpellDescription$ As CARDNAME enters the battlefield, choose a player.
|
||||||
S:Mode$ Continuous | AddKeyword$ Protection from the chosen player | Affected$ Card.Self | Description$ CARDNAME has protection from that player. (This creature can't be blocked, targeted, dealt damage, or enchanted by anything controlled by that player.)
|
S:Mode$ Continuous | AddKeyword$ Protection:Player.PlayerUID_ChosenPlayerUID:Protection from ChosenPlayerName | Affected$ Card.Self | Description$ CARDNAME has protection from that player. (This creature can't be blocked, targeted, dealt damage, or enchanted by anything controlled by that player.)
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/true_name_nemesis.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/true_name_nemesis.jpg
|
||||||
Oracle:As True-Name Nemesis enters the battlefield, choose a player.\nTrue-Name Nemesis has protection from the chosen player. (This creature can't be blocked, targeted, dealt damage, or enchanted by anything controlled by that player.)
|
Oracle:As True-Name Nemesis enters the battlefield, choose a player.\nTrue-Name Nemesis has protection from the chosen player. (This creature can't be blocked, targeted, dealt damage, or enchanted by anything controlled by that player.)
|
||||||
|
|||||||
Reference in New Issue
Block a user