...
 
Commits (50)
...@@ -1339,7 +1339,7 @@ public class ChangeZoneAi extends SpellAbilityAi { ...@@ -1339,7 +1339,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
}); });
for (Card pw : aiPlaneswalkers) { for (Card pw : aiPlaneswalkers) {
int curLoyalty = pw.getCounters(CounterType.LOYALTY); int curLoyalty = pw.getCounters(CounterType.LOYALTY);
int freshLoyalty = pw.getCurrentState().getBaseLoyalty(); int freshLoyalty = Integer.valueOf(pw.getCurrentState().getBaseLoyalty());
if (freshLoyalty - curLoyalty >= loyaltyDiff && curLoyalty <= maxLoyaltyToConsider) { if (freshLoyalty - curLoyalty >= loyaltyDiff && curLoyalty <= maxLoyaltyToConsider) {
return pw; return pw;
} }
......
...@@ -290,7 +290,6 @@ public class GameCopier { ...@@ -290,7 +290,6 @@ public class GameCopier {
// TODO: Is this correct? Does it not duplicate keywords from enchantments and such? // TODO: Is this correct? Does it not duplicate keywords from enchantments and such?
for (KeywordInterface kw : c.getHiddenExtrinsicKeywords()) for (KeywordInterface kw : c.getHiddenExtrinsicKeywords())
newCard.addHiddenExtrinsicKeyword(kw); newCard.addHiddenExtrinsicKeyword(kw);
newCard.setExtrinsicKeyword(Lists.newArrayList(c.getExtrinsicKeyword()));
if (c.isTapped()) { if (c.isTapped()) {
newCard.setTapped(true); newCard.setTapped(true);
} }
......
...@@ -38,7 +38,7 @@ final class CardFace implements ICardFace { ...@@ -38,7 +38,7 @@ final class CardFace implements ICardFace {
private int iToughness = Integer.MAX_VALUE; private int iToughness = Integer.MAX_VALUE;
private String power = null; private String power = null;
private String toughness = null; private String toughness = null;
private int initialLoyalty = -1; private String initialLoyalty = "";
private String nonAbilityText = null; private String nonAbilityText = null;
private List<String> keywords = null; private List<String> keywords = null;
...@@ -56,7 +56,7 @@ final class CardFace implements ICardFace { ...@@ -56,7 +56,7 @@ final class CardFace implements ICardFace {
@Override public int getIntToughness() { return iToughness; } @Override public int getIntToughness() { return iToughness; }
@Override public String getPower() { return power; } @Override public String getPower() { return power; }
@Override public String getToughness() { return toughness; } @Override public String getToughness() { return toughness; }
@Override public int getInitialLoyalty() { return initialLoyalty; } @Override public String getInitialLoyalty() { return initialLoyalty; }
@Override public String getName() { return this.name; } @Override public String getName() { return this.name; }
@Override public CardType getType() { return this.type; } @Override public CardType getType() { return this.type; }
@Override public ManaCost getManaCost() { return this.manaCost; } @Override public ManaCost getManaCost() { return this.manaCost; }
...@@ -84,7 +84,7 @@ final class CardFace implements ICardFace { ...@@ -84,7 +84,7 @@ final class CardFace implements ICardFace {
void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; } void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; }
void setColor(ColorSet color0) { this.color = color0; } void setColor(ColorSet color0) { this.color = color0; }
void setOracleText(String text) { this.oracleText = text; } void setOracleText(String text) { this.oracleText = text; }
void setInitialLoyalty(int value) { this.initialLoyalty = value; } void setInitialLoyalty(String value) { this.initialLoyalty = value; }
void setPtText(String value) { void setPtText(String value) {
final String k[] = value.split("/"); final String k[] = value.split("/");
......
...@@ -186,7 +186,7 @@ public final class CardRules implements ICardCharacteristics { ...@@ -186,7 +186,7 @@ public final class CardRules implements ICardCharacteristics {
@Override public int getIntToughness() { return mainPart.getIntToughness(); } @Override public int getIntToughness() { return mainPart.getIntToughness(); }
@Override public String getPower() { return mainPart.getPower(); } @Override public String getPower() { return mainPart.getPower(); }
@Override public String getToughness() { return mainPart.getToughness(); } @Override public String getToughness() { return mainPart.getToughness(); }
@Override public int getInitialLoyalty() { return mainPart.getInitialLoyalty(); } @Override public String getInitialLoyalty() { return mainPart.getInitialLoyalty(); }
@Override @Override
public String getOracleText() { public String getOracleText() {
...@@ -409,7 +409,7 @@ public final class CardRules implements ICardCharacteristics { ...@@ -409,7 +409,7 @@ public final class CardRules implements ICardCharacteristics {
case 'L': case 'L':
if ("Loyalty".equals(key)) { if ("Loyalty".equals(key)) {
this.faces[this.curFace].setInitialLoyalty(Integer.valueOf(value)); this.faces[this.curFace].setInitialLoyalty(value);
} }
break; break;
......
...@@ -12,7 +12,7 @@ public interface ICardCharacteristics { ...@@ -12,7 +12,7 @@ public interface ICardCharacteristics {
int getIntToughness(); int getIntToughness();
String getPower(); String getPower();
String getToughness(); String getToughness();
int getInitialLoyalty(); String getInitialLoyalty();
String getOracleText(); String getOracleText();
} }
...@@ -376,6 +376,9 @@ public class GameAction { ...@@ -376,6 +376,9 @@ public class GameAction {
copied.clearEtbCounters(); copied.clearEtbCounters();
} }
// update state for view
copied.updateStateForView();
if (fromBattlefield) { if (fromBattlefield) {
c.setDamage(0); //clear damage after a card leaves the battlefield c.setDamage(0); //clear damage after a card leaves the battlefield
c.setHasBeenDealtDeathtouchDamage(false); c.setHasBeenDealtDeathtouchDamage(false);
......
...@@ -204,7 +204,8 @@ public final class AbilityFactory { ...@@ -204,7 +204,8 @@ public final class AbilityFactory {
else if (api == ApiType.PermanentCreature || api == ApiType.PermanentNoncreature) { else if (api == ApiType.PermanentCreature || api == ApiType.PermanentNoncreature) {
// If API is a permanent type, and creating AF Spell // If API is a permanent type, and creating AF Spell
// Clear out the auto created SpellPemanent spell // Clear out the auto created SpellPemanent spell
if (type == AbilityRecordType.Spell && !mapParams.containsKey("SubAbility")) { if (type == AbilityRecordType.Spell
&& !mapParams.containsKey("SubAbility") && !mapParams.containsKey("NonBasicSpell")) {
hostCard.clearFirstSpell(); hostCard.clearFirstSpell();
} }
} }
...@@ -389,6 +390,10 @@ public final class AbilityFactory { ...@@ -389,6 +390,10 @@ public final class AbilityFactory {
sa.setBasicSpell(false); sa.setBasicSpell(false);
} }
if (mapParams.containsKey("Dash")) {
sa.setDash(true);
}
if (mapParams.containsKey("Outlast")) { if (mapParams.containsKey("Outlast")) {
sa.setOutlast(true); sa.setOutlast(true);
} }
......
...@@ -238,7 +238,7 @@ public abstract class SpellAbilityEffect { ...@@ -238,7 +238,7 @@ public abstract class SpellAbilityEffect {
} }
sb.append(Lang.joinHomogenous(crds)); sb.append(Lang.joinHomogenous(crds));
if (location.equals("Hand")) { if (location.equals("Hand")) {
sb.append("to your hand").append(" "); sb.append(" to your hand");
} }
sb.append(" at the "); sb.append(" at the ");
if (combat) { if (combat) {
......
...@@ -134,6 +134,9 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect { ...@@ -134,6 +134,9 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
&& !sa.hasParam("Shuffle") && cards.size() >= 2 && !random) { && !sa.hasParam("Shuffle") && cards.size() >= 2 && !random) {
Player p = AbilityUtils.getDefinedPlayers(source, sa.getParamOrDefault("DefinedPlayer", "You"), sa).get(0); Player p = AbilityUtils.getDefinedPlayers(source, sa.getParamOrDefault("DefinedPlayer", "You"), sa).get(0);
cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination); cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination);
//the last card in this list will be the closest to the top, but we want the first card to be closest.
//so reverse it here before moving them to the library.
java.util.Collections.reverse(cards);
} }
if (destination == ZoneType.Graveyard) { if (destination == ZoneType.Graveyard) {
......
...@@ -537,10 +537,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect { ...@@ -537,10 +537,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
tgtC.getController().getZone(destination), tgtC, sa, null); tgtC.getController().getZone(destination), tgtC, sa, null);
if (sa.hasParam("Unearth")) { if (sa.hasParam("Unearth")) {
movedCard.setUnearthed(true); movedCard.setUnearthed(true);
movedCard.addExtrinsicKeyword("Haste"); movedCard.addChangedCardKeywords(Lists.newArrayList("Haste"), null, false, false,
game.getNextTimestamp(), true);
registerDelayedTrigger(sa, "Exile", Lists.newArrayList(movedCard)); registerDelayedTrigger(sa, "Exile", Lists.newArrayList(movedCard));
addLeaveBattlefieldReplacement(movedCard, sa, "Exile"); addLeaveBattlefieldReplacement(movedCard, sa, "Exile");
movedCard.updateStateForView();
} }
if (sa.hasParam("FaceDown")) { if (sa.hasParam("FaceDown")) {
movedCard.turnFaceDown(true); movedCard.turnFaceDown(true);
......
...@@ -52,7 +52,7 @@ public class ChooseCardEffect extends SpellAbilityEffect { ...@@ -52,7 +52,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
} }
CardCollectionView choices = game.getCardsIn(choiceZone); CardCollectionView choices = game.getCardsIn(choiceZone);
if (sa.hasParam("Choices")) { if (sa.hasParam("Choices")) {
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host); choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host, sa);
} }
if (sa.hasParam("TargetControls")) { if (sa.hasParam("TargetControls")) {
choices = CardLists.filterControlledBy(choices, tgtPlayers.get(0)); choices = CardLists.filterControlledBy(choices, tgtPlayers.get(0));
......
...@@ -3,6 +3,8 @@ package forge.game.ability.effects; ...@@ -3,6 +3,8 @@ package forge.game.ability.effects;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import com.google.common.collect.Lists;
import forge.GameCommand; import forge.GameCommand;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.Game; import forge.game.Game;
...@@ -11,6 +13,7 @@ import forge.game.ability.SpellAbilityEffect; ...@@ -11,6 +13,7 @@ import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.Ability; import forge.game.spellability.Ability;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
...@@ -35,23 +38,26 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -35,23 +38,26 @@ public class ControlGainEffect extends SpellAbilityEffect {
if (tgts.isEmpty()) { if (tgts.isEmpty()) {
sb.append(" (nothing)"); sb.append(" (nothing)");
} else { } else {
for (final Card c : getDefinedCards(sa)) { for (final Card c : tgts) {
sb.append(" "); sb.append(" ");
if (c.isFaceDown()) { if (c.isFaceDown()) {
sb.append("Face-down creature (").append(c.getId()).append(')'); sb.append("Face-down creature (").append(c.getId()).append(')');
} else { } else {
sb.append(c); sb.append(c);
} }
} }
} }
sb.append("."); sb.append(".");
if (sa.hasParam("Untap")) {
sb.append(" Untap it.");
}
return sb.toString(); return sb.toString();
} }
private static void doLoseControl(final Card c, final Card host, private static void doLoseControl(final Card c, final Card host,
final boolean tapOnLose, final List<String> addedKeywords, final boolean tapOnLose, final long tStamp) {
final long tStamp) {
if (null == c || c.hasKeyword("Other players can't gain control of CARDNAME.")) { if (null == c || c.hasKeyword("Other players can't gain control of CARDNAME.")) {
return; return;
} }
...@@ -61,12 +67,6 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -61,12 +67,6 @@ public class ControlGainEffect extends SpellAbilityEffect {
if (tapOnLose) { if (tapOnLose) {
c.tap(); c.tap();
} }
if (null != addedKeywords) {
for (final String kw : addedKeywords) {
c.removeExtrinsicKeyword(kw);
}
}
} // if } // if
host.removeGainControlTargets(c); host.removeGainControlTargets(c);
...@@ -82,7 +82,7 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -82,7 +82,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
final boolean remember = sa.hasParam("RememberControlled"); final boolean remember = sa.hasParam("RememberControlled");
final boolean forget = sa.hasParam("ForgetControlled"); final boolean forget = sa.hasParam("ForgetControlled");
final List<String> destroyOn = sa.hasParam("DestroyTgt") ? Arrays.asList(sa.getParam("DestroyTgt").split(",")) : null; final List<String> destroyOn = sa.hasParam("DestroyTgt") ? Arrays.asList(sa.getParam("DestroyTgt").split(",")) : null;
final List<String> kws = sa.hasParam("AddKWs") ? Arrays.asList(sa.getParam("AddKWs").split(" & ")) : null; final List<String> keywords = sa.hasParam("AddKWs") ? Arrays.asList(sa.getParam("AddKWs").split(" & ")) : null;
final List<String> lose = sa.hasParam("LoseControl") ? Arrays.asList(sa.getParam("LoseControl").split(",")) : null; final List<String> lose = sa.hasParam("LoseControl") ? Arrays.asList(sa.getParam("LoseControl").split(",")) : null;
final List<Player> controllers = getDefinedPlayersOrTargeted(sa, "NewController"); final List<Player> controllers = getDefinedPlayersOrTargeted(sa, "NewController");
...@@ -125,15 +125,22 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -125,15 +125,22 @@ public class ControlGainEffect extends SpellAbilityEffect {
tgtC.untap(); tgtC.untap();
} }
if (null != kws) { final List<String> kws = Lists.newArrayList();
for (final String kw : kws) { if (null != keywords) {
tgtC.addExtrinsicKeyword(kw); for (final String kw : keywords) {
if (kw.equals("Haste")) { if (kw.startsWith("HIDDEN")) {
tgtC.updateStateForView(); // ensure that summoning sickness icon is removed tgtC.addHiddenExtrinsicKeyword(kw);
} else {
kws.add(kw);
} }
} }
} }
if (!kws.isEmpty()) {
tgtC.addChangedCardKeywords(kws, Lists.<String>newArrayList(), false, false, tStamp);
game.fireEvent(new GameEventCardStatsChanged(tgtC));
}
if (remember && !sa.getHostCard().isRemembered(tgtC)) { if (remember && !sa.getHostCard().isRemembered(tgtC)) {
sa.getHostCard().addRemembered(tgtC); sa.getHostCard().addRemembered(tgtC);
} }
...@@ -143,7 +150,7 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -143,7 +150,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
} }
if (lose != null) { if (lose != null) {
final GameCommand loseControl = getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws); final GameCommand loseControl = getLoseControlCommand(tgtC, tStamp, bTapOnLose, source);
if (lose.contains("LeavesPlay")) { if (lose.contains("LeavesPlay")) {
sa.getHostCard().addLeavesPlayCommand(loseControl); sa.getHostCard().addLeavesPlayCommand(loseControl);
} }
...@@ -183,6 +190,26 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -183,6 +190,26 @@ public class ControlGainEffect extends SpellAbilityEffect {
} }
} }
if (keywords != null) {
// Add keywords only until end of turn
final GameCommand untilKeywordEOT = new GameCommand() {
private static final long serialVersionUID = -42244224L;
@Override
public void run() {
if (keywords.size() > 0) {
for (String kw : keywords) {
if (kw.startsWith("HIDDEN")) {
tgtC.removeHiddenExtrinsicKeyword(kw);
}
}
tgtC.removeChangedCardKeywords(tStamp);
}
}
};
game.getEndOfTurn().addUntil(untilKeywordEOT);
}
game.getAction().controllerChangeZoneCorrection(tgtC); game.getAction().controllerChangeZoneCorrection(tgtC);
} // end foreach target } // end foreach target
} }
...@@ -236,14 +263,13 @@ public class ControlGainEffect extends SpellAbilityEffect { ...@@ -236,14 +263,13 @@ public class ControlGainEffect extends SpellAbilityEffect {
* @return a {@link forge.GameCommand} object. * @return a {@link forge.GameCommand} object.
*/ */
private static GameCommand getLoseControlCommand(final Card c, private static GameCommand getLoseControlCommand(final Card c,
final long tStamp, final boolean bTapOnLose, final Card hostCard, final long tStamp, final boolean bTapOnLose, final Card hostCard) {
final List<String> kws) {
final GameCommand loseControl = new GameCommand() { final GameCommand loseControl = new GameCommand() {
private static final long serialVersionUID = 878543373519872418L; private static final long serialVersionUID = 878543373519872418L;
@Override @Override
public void run() { public void run() {
doLoseControl(c, hostCard, bTapOnLose, kws, tStamp); doLoseControl(c, hostCard, bTapOnLose, tStamp);
c.getSVars().remove("SacMe"); c.getSVars().remove("SacMe");
} }
}; };
......
...@@ -83,10 +83,6 @@ public class DigEffect extends SpellAbilityEffect { ...@@ -83,10 +83,6 @@ public class DigEffect extends SpellAbilityEffect {
boolean changeAll = false; boolean changeAll = false;
boolean allButOne = false; boolean allButOne = false;
final List<String> keywords = new ArrayList<String>();
if (sa.hasParam("Keywords")) {
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
}
if (sa.hasParam("ChangeNum")) { if (sa.hasParam("ChangeNum")) {
if (sa.getParam("ChangeNum").equalsIgnoreCase("All")) { if (sa.getParam("ChangeNum").equalsIgnoreCase("All")) {
...@@ -307,9 +303,6 @@ public class DigEffect extends SpellAbilityEffect { ...@@ -307,9 +303,6 @@ public class DigEffect extends SpellAbilityEffect {
else { else {
c = game.getAction().moveTo(zone, c, sa); c = game.getAction().moveTo(zone, c, sa);
if (destZone1.equals(ZoneType.Battlefield)) { if (destZone1.equals(ZoneType.Battlefield)) {
for (final String kw : keywords) {
c.addExtrinsicKeyword(kw);
}
if (sa.hasParam("Tapped")) { if (sa.hasParam("Tapped")) {
c.setTapped(true); c.setTapped(true);
} }
...@@ -377,11 +370,7 @@ public class DigEffect extends SpellAbilityEffect { ...@@ -377,11 +370,7 @@ public class DigEffect extends SpellAbilityEffect {
if (!origin.equals(c.getZone().getZoneType())) { if (!origin.equals(c.getZone().getZoneType())) {
table.put(origin, c.getZone().getZoneType(), c); table.put(origin, c.getZone().getZoneType(), c);
} }
if (destZone2 == ZoneType.Battlefield && !keywords.isEmpty()) { if (destZone2 == ZoneType.Exile) {
for (final String kw : keywords) {
c.addExtrinsicKeyword(kw);
}
} else if (destZone2 == ZoneType.Exile) {
if (sa.hasParam("ExileWithCounter")) { if (sa.hasParam("ExileWithCounter")) {
c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")), c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")),
1, player, true, counterTable); 1, player, true, counterTable);
......
package forge.game.ability.effects; package forge.game.ability.effects;
import com.google.common.collect.Lists;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.player.Player; import forge.game.player.Player;
...@@ -25,9 +27,8 @@ public class PermanentEffect extends SpellAbilityEffect { ...@@ -25,9 +27,8 @@ public class PermanentEffect extends SpellAbilityEffect {
// some extra for Dashing // some extra for Dashing
if (sa.isDash()) { if (sa.isDash()) {
c.addExtrinsicKeyword("Haste");
c.setSVar("EndOfTurnLeavePlay", "Dash"); c.setSVar("EndOfTurnLeavePlay", "Dash");
c.updateKeywords(); registerDelayedTrigger(sa, "Hand", Lists.newArrayList(c));
} }
} }
} }
...@@ -94,7 +94,6 @@ public class Card extends GameEntity implements Comparable<Card> { ...@@ -94,7 +94,6 @@ public class Card extends GameEntity implements Comparable<Card> {
private final CardDamageHistory damageHistory = new CardDamageHistory(); private final CardDamageHistory damageHistory = new CardDamageHistory();
private Map<Card, Map<CounterType, Integer>> countersAddedBy = Maps.newTreeMap(); private Map<Card, Map<CounterType, Integer>> countersAddedBy = Maps.newTreeMap();
private KeywordCollection extrinsicKeyword = new KeywordCollection();
// Hidden keywords won't be displayed on the card // Hidden keywords won't be displayed on the card
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection(); private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
...@@ -540,8 +539,7 @@ public class Card extends GameEntity implements Comparable<Card> { ...@@ -540,8 +539,7 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
public final void updatePowerToughnessForView() { public final void updatePowerToughnessForView() {
currentState.getView().updatePower(this); view.updateCounters(this);
currentState.getView().updateToughness(this);
} }
public final void updateTypesForView() { public final void updateTypesForView() {
...@@ -2698,6 +2696,13 @@ public class Card extends GameEntity implements Comparable<Card> { ...@@ -2698,6 +2696,13 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
public final Player getController() { public final Player getController() {
if ((currentZone == null) || ((currentZone.getZoneType() != ZoneType.Battlefield) && (currentZone.getZoneType() != ZoneType.Stack))){
//only permanents and spells have controllers [108.4],
//so a card really only has a controller while it's on the stack or battlefield.
//everywhere else, just use the owner [108.4a].
return owner;
}
Entry<Long, Player> lastEntry = tempControllers.lastEntry(); Entry<Long, Player> lastEntry = tempControllers.lastEntry();
if (lastEntry != null) { if (lastEntry != null) {
final long lastTimestamp = lastEntry.getKey(); final long lastTimestamp = lastEntry.getKey();
...@@ -3727,7 +3732,6 @@ public class Card extends GameEntity implements Comparable<Card> { ...@@ -3727,7 +3732,6 @@ public class Card extends GameEntity implements Comparable<Card> {
if (!removeIntrinsic) { if (!removeIntrinsic) {
keywords.insertAll(state.getIntrinsicKeywords()); keywords.insertAll(state.getIntrinsicKeywords());
} }
keywords.insertAll(extrinsicKeyword.getValues());
// see if keyword changes are in effect // see if keyword changes are in effect
for (final KeywordsChange ck : changedCardKeywords.values()) { for (final KeywordsChange ck : changedCardKeywords.values()) {
...@@ -3755,11 +3759,6 @@ public class Card extends GameEntity implements Comparable<Card> { ...@@ -3755,11 +3759,6 @@ public class Card extends GameEntity implements Comparable<Card> {
return; return;
} }
} }
for (KeywordInterface kw : extrinsicKeyword.getValues()) {
if (!visitor.visit(kw)) {
return;
}
}
} else { } else {
for (KeywordInterface kw : getUnhiddenKeywords(state)) { for (KeywordInterface kw : getUnhiddenKeywords(state)) {
if (!visitor.visit(kw)) { if (!visitor.visit(kw)) {
...@@ -3927,53 +3926,6 @@ public class Card extends GameEntity implements Comparable<Card> { ...@@ -3927,53 +3926,6 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
} }
public Collection<KeywordInterface> getExtrinsicKeyword() {
return extrinsicKeyword.getValues();
}
public final void setExtrinsicKeyword(final List<String> a) {
extrinsicKeyword.clear();
extrinsicKeyword.addAll(a);
}
public void setExtrinsicKeyword(Collection<KeywordInterface> extrinsicKeyword2) {
extrinsicKeyword.clear();
extrinsicKeyword.insertAll(extrinsicKeyword2);
}
public void addExtrinsicKeyword(final String s) {
if (s.startsWith("HIDDEN")) {
addHiddenExtrinsicKeyword(s);
}
else {
extrinsicKeyword.add(s);
}
}
public void removeExtrinsicKeyword(final String s) {
if (s.startsWith("HIDDEN")) {
removeHiddenExtrinsicKeyword(s);
}
else if (extrinsicKeyword.remove(s)) {
currentState.getView().updateKeywords(this, currentState);
}
}
public void removeAllExtrinsicKeyword(final String s) {
final List<String> strings = Lists.newArrayList();
strings.add(s);
boolean needKeywordUpdate = false;
if (extrinsicKeyword.removeAll(strings)) {
needKeywordUpdate = true;
}
strings.add("HIDDEN " + s);
if (hiddenExtrinsicKeyword.removeAll(strings)) {
view.updateNonAbilityText(this);
needKeywordUpdate = true;
}
if (needKeywordUpdate) {
currentState.getView().updateKeywords(this, currentState);
}
}
// Hidden Keywords will be returned without the indicator HIDDEN // Hidden Keywords will be returned without the indicator HIDDEN
public final List<KeywordInterface> getHiddenExtrinsicKeywords() { public final List<KeywordInterface> getHiddenExtrinsicKeywords() {
ListKeywordVisitor visitor = new ListKeywordVisitor(); ListKeywordVisitor visitor = new ListKeywordVisitor();
......
...@@ -325,9 +325,6 @@ public class CardFactory { ...@@ -325,9 +325,6 @@ public class CardFactory {
// ****************************************************************** // ******************************************************************
// ************** Link to different CardFactories ******************* // ************** Link to different CardFactories *******************
if (card.isPlaneswalker()) {
buildPlaneswalkerAbilities(card);
}
if (state == CardStateName.LeftSplit || state == CardStateName.RightSplit) { if (state == CardStateName.LeftSplit || state == CardStateName.RightSplit) {
for (final SpellAbility sa : card.getSpellAbilities()) { for (final SpellAbility sa : card.getSpellAbilities()) {
...@@ -383,18 +380,6 @@ public class CardFactory { ...@@ -383,18 +380,6 @@ public class CardFactory {
card.addSpellAbility(planarRoll); card.addSpellAbility(planarRoll);
} }
private static void buildPlaneswalkerAbilities(Card card) {
CardState state = card.getCurrentState();
// etbCounter only for Original Card
if (state.getBaseLoyalty() > 0) {
final String loyalty = Integer.toString(state.getBaseLoyalty());
// keyword need to be added to state directly, so init can be disabled
if (state.addIntrinsicKeyword("etbCounter:LOYALTY:" + loyalty + ":no Condition:no desc", false) != null) {
card.updateKeywords();
}
}
}
private static Card readCard(final CardRules rules, final IPaperCard paperCard, int cardId, Game game) { private static Card readCard(final CardRules rules, final IPaperCard paperCard, int cardId, Game game) {
final Card card = new Card(cardId, paperCard, game); final Card card = new Card(cardId, paperCard, game);
......
...@@ -3508,7 +3508,7 @@ public class CardFactoryUtil { ...@@ -3508,7 +3508,7 @@ public class CardFactoryUtil {
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 it's manacost."; + " 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
String abPlay = "DB$ Play | Defined$ Self | WithoutManaCost$ True | Optional$ True"; String abPlay = "DB$ Play | Defined$ Self | WithoutManaCost$ True | Optional$ True";
...@@ -3850,23 +3850,11 @@ public class CardFactoryUtil { ...@@ -3850,23 +3850,11 @@ public class CardFactoryUtil {
inst.addSpellAbility(sa); inst.addSpellAbility(sa);
} else if (keyword.startsWith("Dash")) { } else if (keyword.startsWith("Dash")) {
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
final String dashString = "SP$ PermanentCreature | Cost$ " + k[1] + " | SubAbility$" final String dashString = "SP$ PermanentCreature | Cost$ " + k[1] + " | StackDescription$ CARDNAME (Dash)"
+ " DashDelayedTrigger"; + " | Dash$ True | NonBasicSpell$ True"
final String dbDelayTrigger = "DB$ DelayedTrigger | Mode$ Phase | Phase$" + " | SpellDescription$ Dash " + ManaCostParser.parse(k[1]) + " (" + inst.getReminderText() + ")";
+ " End of Turn | Execute$ DashReturnSelf | RememberObjects$ Self"
+ " | TriggerDescription$ Return CARDNAME from the battlefield to" + " its owner's hand.";
final String dbReturn = "DB$ ChangeZone | Origin$ Battlefield | Destination$ Hand"
+ " | Defined$ DelayTriggerRemembered";
card.setSVar("DashDelayedTrigger", dbDelayTrigger);
card.setSVar("DashReturnSelf", dbReturn);
final SpellAbility newSA = AbilityFactory.getAbility(dashString, card); final SpellAbility newSA = AbilityFactory.getAbility(dashString, card);
String desc = "Dash " + ManaCostParser.parse(k[1]) + " (" + inst.getReminderText()
+ ")";
newSA.setStackDescription(card.getName() + " (Dash)");
newSA.setDescription(desc);
newSA.setBasicSpell(false);
newSA.setDash(true);
newSA.setIntrinsic(intrinsic); newSA.setIntrinsic(intrinsic);
newSA.setTemporary(!intrinsic); newSA.setTemporary(!intrinsic);
...@@ -4527,6 +4515,8 @@ public class CardFactoryUtil { ...@@ -4527,6 +4515,8 @@ public class CardFactoryUtil {
card.setSVar("CipherTrigger", trig); card.setSVar("CipherTrigger", trig);
card.setSVar("PlayEncoded", ab); card.setSVar("PlayEncoded", ab);
} else if (keyword.startsWith("Dash")) {
effect = "Mode$ Continuous | Affected$ Card.Self+dashed | AddKeyword$ Haste";
} else if (keyword.equals("Devoid")) { } else if (keyword.equals("Devoid")) {
effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" + effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" +
" | CharacteristicDefining$ True | SetColor$ Colorless | Secondary$ True" + " | CharacteristicDefining$ True | SetColor$ Colorless | Secondary$ True" +
......
...@@ -1639,6 +1639,11 @@ public class CardProperty { ...@@ -1639,6 +1639,11 @@ public class CardProperty {
return false; return false;
} }
return card.getCastSA().isSurged(); return card.getCastSA().isSurged();
} else if (property.startsWith("dashed")) {
if (card.getCastSA() == null) {
return false;
}
return card.getCastSA().isDash();
} else if (property.startsWith("evoked")) { } else if (property.startsWith("evoked")) {
if (card.getCastSA() == null) { if (card.getCastSA() == null) {
return false; return false;
......
...@@ -53,7 +53,7 @@ public class CardState extends GameObject { ...@@ -53,7 +53,7 @@ public class CardState extends GameObject {
private byte color = MagicColor.COLORLESS; private byte color = MagicColor.COLORLESS;
private int basePower = 0; private int basePower = 0;
private int baseToughness = 0; private int baseToughness = 0;
private int baseLoyalty = 0; private String baseLoyalty = "";
private KeywordCollection intrinsicKeywords = new KeywordCollection(); private KeywordCollection intrinsicKeywords = new KeywordCollection();
private final FCollection<SpellAbility> nonManaAbilities = new FCollection<SpellAbility>(); private final FCollection<SpellAbility> nonManaAbilities = new FCollection<SpellAbility>();
...@@ -72,6 +72,8 @@ public class CardState extends GameObject { ...@@ -72,6 +72,8 @@ public class CardState extends GameObject {
private final CardStateView view; private final CardStateView view;
private final Card card; private final Card card;
private ReplacementEffect loyaltyRep = null;
public CardState(Card card, CardStateName name) { public CardState(Card card, CardStateName name) {
this(card.getView().createAlternateState(name), card); this(card.getView().createAlternateState(name), card);
} }
...@@ -174,11 +176,11 @@ public class CardState extends GameObject { ...@@ -174,11 +176,11 @@ public class CardState extends GameObject {
view.updateToughness(this); view.updateToughness(this);
} }
public int getBaseLoyalty() { public String getBaseLoyalty() {
return baseLoyalty; return baseLoyalty;
} }
public final void setBaseLoyalty(final int loyalty) { public final void setBaseLoyalty(final String string) {
baseLoyalty = loyalty; baseLoyalty = string;
view.updateLoyalty(this); view.updateLoyalty(this);
} }
...@@ -400,6 +402,14 @@ public class CardState extends GameObject { ...@@ -400,6 +402,14 @@ public class CardState extends GameObject {
public FCollectionView<ReplacementEffect> getReplacementEffects() { public FCollectionView<ReplacementEffect> getReplacementEffects() {
FCollection<ReplacementEffect> result = new FCollection<>(replacementEffects); FCollection<ReplacementEffect> result = new FCollection<>(replacementEffects);
if (getTypeWithChanges().isPlaneswalker()) {
if (loyaltyRep == null) {
loyaltyRep = CardFactoryUtil.makeEtbCounter("etbCounter:LOYALTY:" + this.baseLoyalty, card, true);
}
result.add(loyaltyRep);
}
card.updateReplacementEffects(result, this); card.updateReplacementEffects(result, this);
return result; return result;
} }
......
...@@ -255,7 +255,6 @@ public final class CardUtil { ...@@ -255,7 +255,6 @@ public final class CardUtil {
newCopy.setBaseToughness(in.getCurrentToughness() + in.getTempToughnessBoost() + in.getSemiPermanentToughnessBoost()); newCopy.setBaseToughness(in.getCurrentToughness() + in.getTempToughnessBoost() + in.getSemiPermanentToughnessBoost());
newCopy.setCounters(Maps.newEnumMap(in.getCounters())); newCopy.setCounters(Maps.newEnumMap(in.getCounters()));
newCopy.setExtrinsicKeyword(in.getExtrinsicKeyword());
newCopy.setColor(in.determineColor().getColor()); newCopy.setColor(in.determineColor().getColor());
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn()); newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
......
...@@ -659,6 +659,8 @@ public class CardView extends GameEntityView { ...@@ -659,6 +659,8 @@ public class CardView extends GameEntityView {
if (c.getGame() != null) { if (c.getGame() != null) {
currentStateView.updateColors(currentState); currentStateView.updateColors(currentState);
} }
} else {
currentStateView.updateLoyalty(currentState);
} }
currentState.getView().updateKeywords(c, currentState); //update keywords even if state doesn't change currentState.getView().updateKeywords(c, currentState); //update keywords even if state doesn't change
...@@ -685,6 +687,8 @@ public class CardView extends GameEntityView { ...@@ -685,6 +687,8 @@ public class CardView extends GameEntityView {
if (c.getGame() != null) { if (c.getGame() != null) {
alternateStateView.updateColors(alternateState); alternateStateView.updateColors(alternateState);
} }
} else {
alternateStateView.updateLoyalty(alternateState);
} }
alternateState.getView().updateKeywords(c, alternateState); alternateState.getView().updateKeywords(c, alternateState);
} }
...@@ -889,13 +893,17 @@ public class CardView extends GameEntityView { ...@@ -889,13 +893,17 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Toughness, c.getBaseToughness()); set(TrackableProperty.Toughness, c.getBaseToughness());
} }
public int getLoyalty() { public String getLoyalty() {
return get(TrackableProperty.Loyalty); return get(TrackableProperty.Loyalty);
} }
void updateLoyalty(Card c) { void updateLoyalty(Card c) {
updateLoyalty(c.getCurrentLoyalty()); if (c.isInZone(ZoneType.Battlefield)) {
updateLoyalty(String.valueOf(c.getCurrentLoyalty()));
} else {
updateLoyalty(c.getCurrentState().getBaseLoyalty());
}
} }
void updateLoyalty(int loyalty) { void updateLoyalty(String loyalty) {
set(TrackableProperty.Loyalty, loyalty); set(TrackableProperty.Loyalty, loyalty);
} }
void updateLoyalty(CardState c) { void updateLoyalty(CardState c) {
...@@ -911,7 +919,7 @@ public class CardView extends GameEntityView { ...@@ -911,7 +919,7 @@ public class CardView extends GameEntityView {
return; return;
} }
} }
set(TrackableProperty.Loyalty, 0); //alternates don't need loyalty set(TrackableProperty.Loyalty, "0"); //alternates don't need loyalty
} }
public String getSetCode() { public String getSetCode() {
......
...@@ -209,11 +209,10 @@ public class Untap extends Phase { ...@@ -209,11 +209,10 @@ public class Untap extends Phase {
// Remove temporary keywords // Remove temporary keywords
for (final Card c : player.getCardsIn(ZoneType.Battlefield)) { for (final Card c : player.getCardsIn(ZoneType.Battlefield)) {
c.removeAllExtrinsicKeyword("This card doesn't untap during your next untap step."); c.removeHiddenExtrinsicKeyword("This card doesn't untap during your next untap step.");
c.removeAllExtrinsicKeyword("HIDDEN This card doesn't untap during your next untap step.");
if (c.hasKeyword("This card doesn't untap during your next two untap steps.")) { if (c.hasKeyword("This card doesn't untap during your next two untap steps.")) {
c.removeAllExtrinsicKeyword("HIDDEN This card doesn't untap during your next two untap steps."); c.removeHiddenExtrinsicKeyword("This card doesn't untap during your next two untap steps.");
c.addHiddenExtrinsicKeyword("HIDDEN This card doesn't untap during your next untap step."); c.addHiddenExtrinsicKeyword("This card doesn't untap during your next untap step.");
} }
} }
......
...@@ -77,7 +77,7 @@ public enum TrackableProperty { ...@@ -77,7 +77,7 @@ public enum TrackableProperty {
RulesText(TrackableTypes.StringType), RulesText(TrackableTypes.StringType),
Power(TrackableTypes.IntegerType), Power(TrackableTypes.IntegerType),
Toughness(TrackableTypes.IntegerType), Toughness(TrackableTypes.IntegerType),
Loyalty(TrackableTypes.IntegerType), Loyalty(TrackableTypes.StringType),
ChangedColorWords(TrackableTypes.StringMapType), ChangedColorWords(TrackableTypes.StringMapType),
ChangedTypes(TrackableTypes.StringMapType), ChangedTypes(TrackableTypes.StringMapType),
HasDeathtouch(TrackableTypes.BooleanType), HasDeathtouch(TrackableTypes.BooleanType),
......
...@@ -28,6 +28,11 @@ public enum CSubmenuDownloaders implements ICDoc { ...@@ -28,6 +28,11 @@ public enum CSubmenuDownloaders implements ICDoc {
new GuiDownloader(new GuiDownloadPicturesLQ()).show(); new GuiDownloader(new GuiDownloadPicturesLQ()).show();
} }
}; };
private final UiCommand cmdPicDownloadHQ = new UiCommand() {
@Override public void run() {
new GuiDownloader(new GuiDownloadPicturesHQ()).show();
}
};
private final UiCommand cmdSetDownload = new UiCommand() { private final UiCommand cmdSetDownload = new UiCommand() {
@Override public void run() { @Override public void run() {
new GuiDownloader(new GuiDownloadSetPicturesLQ()).show(); new GuiDownloader(new GuiDownloadSetPicturesLQ()).show();
...@@ -80,6 +85,7 @@ public enum CSubmenuDownloaders implements ICDoc { ...@@ -80,6 +85,7 @@ public enum CSubmenuDownloaders implements ICDoc {
public void initialize() { public void initialize() {
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE; final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
view.setDownloadPicsCommand(cmdPicDownload); view.setDownloadPicsCommand(cmdPicDownload);
view.setDownloadPicsHQCommand(cmdPicDownloadHQ);
view.setDownloadSetPicsCommand(cmdSetDownload); view.setDownloadSetPicsCommand(cmdSetDownload);
view.setDownloadQuestImagesCommand(cmdQuestImages); view.setDownloadQuestImagesCommand(cmdQuestImages);
view.setDownloadAchievementImagesCommand(cmdAchievementImages); view.setDownloadAchievementImagesCommand(cmdAchievementImages);
......
...@@ -57,6 +57,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> { ...@@ -57,6 +57,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics")); private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics"));
private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics")); private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics"));
private final FLabel btnDownloadPicsHQ = _makeButton(localizer.getMessage("btnDownloadPicsHQ"));
private final FLabel btnDownloadQuestImages = _makeButton(localizer.getMessage("btnDownloadQuestImages")); private final FLabel btnDownloadQuestImages = _makeButton(localizer.getMessage("btnDownloadQuestImages"));
private final FLabel btnDownloadAchievementImages = _makeButton(localizer.getMessage("btnDownloadAchievementImages")); private final FLabel btnDownloadAchievementImages = _makeButton(localizer.getMessage("btnDownloadAchievementImages"));
private final FLabel btnReportBug = _makeButton(localizer.getMessage("btnReportBug")); private final FLabel btnReportBug = _makeButton(localizer.getMessage("btnReportBug"));
...@@ -82,6 +83,9 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> { ...@@ -82,6 +83,9 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
pnlContent.add(btnDownloadPics, constraintsBTN); pnlContent.add(btnDownloadPics, constraintsBTN);
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL); pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
pnlContent.add(btnDownloadPicsHQ, constraintsBTN);
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPicsHQ")), constraintsLBL);
pnlContent.add(btnDownloadSetPics, constraintsBTN); pnlContent.add(btnDownloadSetPics, constraintsBTN);
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSetPics")), constraintsLBL); pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSetPics")), constraintsLBL);
...@@ -159,6 +163,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> { ...@@ -159,6 +163,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
} }
public void setDownloadPicsCommand(UiCommand command) { btnDownloadPics.setCommand(command); } public void setDownloadPicsCommand(UiCommand command) { btnDownloadPics.setCommand(command); }
public void setDownloadPicsHQCommand(UiCommand command) { btnDownloadPicsHQ.setCommand(command); }
public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); } public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); }
public void setDownloadQuestImagesCommand(UiCommand command) { btnDownloadQuestImages.setCommand(command); } public void setDownloadQuestImagesCommand(UiCommand command) { btnDownloadQuestImages.setCommand(command); }
public void setDownloadAchievementImagesCommand(UiCommand command) { btnDownloadAchievementImages.setCommand(command); } public void setDownloadAchievementImagesCommand(UiCommand command) { btnDownloadAchievementImages.setCommand(command); }
......
...@@ -437,7 +437,7 @@ public class VAssignDamage { ...@@ -437,7 +437,7 @@ public class VAssignDamage {
} }
else if (defender instanceof CardView) { // planeswalker else if (defender instanceof CardView) { // planeswalker
final CardView pw = (CardView)defender; final CardView pw = (CardView)defender;
lethalDamage = pw.getCurrentState().getLoyalty(); lethalDamage = Integer.valueOf(pw.getCurrentState().getLoyalty());
} }
} }
else { else {
......
...@@ -705,7 +705,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl ...@@ -705,7 +705,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
String sPt = ""; String sPt = "";
if (state.isCreature() && state.isPlaneswalker()) { if (state.isCreature() && state.isPlaneswalker()) {
sPt = state.getPower() + "/" + state.getToughness() + sPt = state.getPower() + "/" + state.getToughness() +
" (" + String.valueOf(state.getLoyalty()) + ")"; " (" + state.getLoyalty() + ")";
} }
else if (state.isCreature()) { else if (state.isCreature()) {
sPt = state.getPower() + "/" + state.getToughness(); sPt = state.getPower() + "/" + state.getToughness();
...@@ -714,7 +714,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl ...@@ -714,7 +714,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
sPt = "[" + state.getPower() + "/" + state.getToughness() + "]"; sPt = "[" + state.getPower() + "/" + state.getToughness() + "]";
} }
else if (state.isPlaneswalker()) { else if (state.isPlaneswalker()) {
sPt = String.valueOf(state.getLoyalty()); sPt = state.getLoyalty();
} }
ptText.setText(sPt); ptText.setText(sPt);
} }
......
...@@ -462,6 +462,26 @@ public class Forge implements ApplicationListener { ...@@ -462,6 +462,26 @@ public class Forge implements ApplicationListener {
if (keyCode == Keys.SHIFT_LEFT || keyCode == Keys.SHIFT_RIGHT) { if (keyCode == Keys.SHIFT_LEFT || keyCode == Keys.SHIFT_RIGHT) {
shiftKeyDown = true; shiftKeyDown = true;
} }
// Cursor keys emulate swipe gestures
// First we touch the screen and later swipe (fling) in the direction of the key pressed
if (keyCode == Keys.LEFT) {
touchDown(0,0,0,0);
return fling(1000,0);
}
if (keyCode == Keys.RIGHT) {
touchDown(0,0,0,0);
return fling(-1000,0);
}
if (keyCode == Keys.UP) {
touchDown(0,0,0,0);
return fling(0,-1000);
}
if (keyCode == Keys.DOWN) {
touchDown(0,0,0,0);
return fling(0,1000);
}
if (keyInputAdapter == null) { if (keyInputAdapter == null) {
if (KeyInputAdapter.isModifierKey(keyCode)) { if (KeyInputAdapter.isModifierKey(keyCode)) {
return false; //don't process modifiers keys for unknown adapter return false; //don't process modifiers keys for unknown adapter
......
package forge.assets;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
import java.util.ArrayList;
import java.util.List;
public class FLanguage {
public static void changeLanguage(final String languageName) {
final ForgePreferences prefs = FModel.getPreferences();
if (languageName.equals(prefs.getPref(FPref.UI_LANGUAGE))) { return; }
//save language preference
prefs.setPref(FPref.UI_LANGUAGE, languageName);
prefs.save();
}
/**
* Gets the languages.
*
* @return the languages
*/
public static Iterable<String> getAllLanguages() {
final List<String> allLanguages = new ArrayList<String>();
final FileHandle dir = Gdx.files.absolute(ForgeConstants.LANG_DIR);
for (FileHandle languageFile : dir.list()) {
String languageName = languageFile.name();
if (!languageName.endsWith(".properties")) { continue; }
allLanguages.add(languageName.replace(".properties", ""));
}
return allLanguages;
}
}
...@@ -273,7 +273,7 @@ public class CardRenderer { ...@@ -273,7 +273,7 @@ public class CardRenderer {
state.getLoyalty(), count, suffix, x, y, w, h, compactMode); state.getLoyalty(), count, suffix, x, y, w, h, compactMode);
} }
public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, FImageComplex cardArt, CardView card, String set, CardRarity rarity, int power, int toughness, int loyalty, int count, String suffix, float x, float y, float w, float h, boolean compactMode) { public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, FImageComplex cardArt, CardView card, String set, CardRarity rarity, int power, int toughness, String loyalty, int count, String suffix, float x, float y, float w, float h, boolean compactMode) {
float cardArtHeight = h + 2 * FList.PADDING; float cardArtHeight = h + 2 * FList.PADDING;
float cardArtWidth = cardArtHeight * CARD_ART_RATIO; float cardArtWidth = cardArtHeight * CARD_ART_RATIO;
if (cardArt != null) { if (cardArt != null) {
......
...@@ -446,7 +446,7 @@ public class VAssignDamage extends FDialog { ...@@ -446,7 +446,7 @@ public class VAssignDamage extends FDialog {
} }
else if (defender instanceof CardView) { // planeswalker else if (defender instanceof CardView) { // planeswalker
CardView pw = (CardView)defender; CardView pw = (CardView)defender;
lethalDamage = pw.getCurrentState().getLoyalty(); lethalDamage = Integer.valueOf(pw.getCurrentState().getLoyalty());
} }
} }
else { else {
......
...@@ -6,6 +6,7 @@ import forge.Graphics; ...@@ -6,6 +6,7 @@ import forge.Graphics;
import forge.MulliganDefs; import forge.MulliganDefs;
import forge.StaticData; import forge.StaticData;
import forge.ai.AiProfileUtil; import forge.ai.AiProfileUtil;
import forge.assets.FLanguage;
import forge.assets.FSkin; import forge.assets.FSkin;
import forge.assets.FSkinColor; import forge.assets.FSkinColor;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
...@@ -48,6 +49,14 @@ public class SettingsPage extends TabPage<SettingsScreen> { ...@@ -48,6 +49,14 @@ public class SettingsPage extends TabPage<SettingsScreen> {
lstSettings.addGroup("Sound Options"); lstSettings.addGroup("Sound Options");
//General Settings //General Settings
lstSettings.addItem(new CustomSelectSetting(FPref.UI_LANGUAGE, "Language",
"Select Language (Excluded Game part. Still a work in progress) (RESTART REQUIRED)",
FLanguage.getAllLanguages()) {
@Override
public void valueChanged(String newValue) {
FLanguage.changeLanguage(newValue);
}
}, 0);
lstSettings.addItem(new CustomSelectSetting(FPref.UI_SKIN, "Theme", lstSettings.addItem(new CustomSelectSetting(FPref.UI_SKIN, "Theme",
"Sets the theme that determines how display components are skinned.", "Sets the theme that determines how display components are skinned.",
FSkin.getAllSkins()) { FSkin.getAllSkins()) {
......
Name:Chance for Glory Name:Chance for Glory
ManaCost:1 R W ManaCost:1 R W
Types:Instant Types:Instant
A:SP$ PumpAll | Cost$ 1 R W | ValidCards$ Creature.YouCtrl | KW$ Indestructible | Permanent$ True | SubAbility$ DBAddTurn | SpellDescription$ Creatures you control gain indestructible. Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. A:SP$ PumpAll | Cost$ 1 R W | ValidCards$ Creature.YouCtrl | KW$ Indestructible | Permanent$ True | SubAbility$ DBAddTurn | SpellDescription$ Creatures you control gain indestructible.
SVar:DBAddTurn:DB$ AddTurn | NumTurns$ 1 | ExtraTurnDelayedTrigger$ DBDelTrig | ExtraTurnDelayedTriggerExcute$ TrigLose | References$ DBDelTrig,TrigLose | SpellDescription$ Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. SVar:DBAddTurn:DB$ AddTurn | NumTurns$ 1 | ExtraTurnDelayedTrigger$ DBDelTrig | ExtraTurnDelayedTriggerExcute$ TrigLose | References$ DBDelTrig,TrigLose | SpellDescription$ Take an extra turn after this one. At the beginning of that turn's end step, you lose the game.
SVar:DBDelTrig:ThisTurn$ True | Mode$ Phase | Phase$ End of Turn | TriggerDescription$ At the beginning of that turn's end step, you lose the game. SVar:DBDelTrig:ThisTurn$ True | Mode$ Phase | Phase$ End of Turn | TriggerDescription$ At the beginning of that turn's end step, you lose the game.
SVar:TrigLose:DB$ LosesGame | Defined$ You SVar:TrigLose:DB$ LosesGame | Defined$ You
......
...@@ -2,8 +2,8 @@ Name:Cruel Celebrant ...@@ -2,8 +2,8 @@ Name:Cruel Celebrant
ManaCost:W B ManaCost:W B
Types:Creature Vampire Types:Creature Vampire
PT:1/2 PT:1/2
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.Other+YouCtrl,Planeswalker.YouCtrl+Other | TriggerZones$ Battlefield | Execute$ TrigDrain | TriggerDescription$ Whenever CARDNAME or another creature you control dies, each opponent loses 1 life and you gain 1 life. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.Other+YouCtrl,Planeswalker.YouCtrl+Other | TriggerZones$ Battlefield | Execute$ TrigDrain | TriggerDescription$ Whenever CARDNAME or another creature or planeswalker you control dies, each opponent loses 1 life and you gain 1 life.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | TriggerController$ TriggeredCardController | Execute$ TrigDrain | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature you control dies, each opponent loses 1 life and you gain 1 life. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | TriggerController$ TriggeredCardController | Execute$ TrigDrain | Secondary$ True | TriggerDescription$ Whenever CARDNAME or another creature or planeswalker you control dies, each opponent loses 1 life and you gain 1 life.
SVar:TrigDrain:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 | SubAbility$ DBGainLife SVar:TrigDrain:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
DeckHas:Ability$LifeGain DeckHas:Ability$LifeGain
......
...@@ -5,7 +5,7 @@ PT:5/5 ...@@ -5,7 +5,7 @@ PT:5/5
K:Kicker:3 K:Kicker:3
K:etbCounter:P1P1:5:CheckSVar$ WasKicked:If CARDNAME was kicked, it enters the battlefield with five +1/+1 counters on it. K:etbCounter:P1P1:5:CheckSVar$ WasKicked:If CARDNAME was kicked, it enters the battlefield with five +1/+1 counters on it.
SVar:WasKicked:Count$Kicked.1.0 SVar:WasKicked:Count$Kicked.1.0
T:Mode$ Attacks | ValidCard$ Card.Self | Alone$ True | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAMRE attacks alone, double its power and toughness until end of turn. T:Mode$ Attacks | ValidCard$ Card.Self | Alone$ True | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks alone, double its power and toughness until end of turn.
SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ +X | NumDef$ +Y | References$ X,Y SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ +X | NumDef$ +Y | References$ X,Y
SVar:X:Count$CardPower SVar:X:Count$CardPower
SVar:Y:Count$CardToughness SVar:Y:Count$CardToughness
......
Name:Nissa, Steward of Elements Name:Nissa, Steward of Elements
ManaCost:X G U ManaCost:X G U
Types:Legendary Planeswalker Nissa Types:Legendary Planeswalker Nissa
Loyalty:0 Loyalty:X
K:etbCounter:LOYALTY:X
SVar:X:Count$xPaid SVar:X:Count$xPaid
A:AB$ Scry | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ScryNum$ 2 | SpellDescription$ Scry 2. A:AB$ Scry | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ScryNum$ 2 | SpellDescription$ Scry 2.
A:AB$ Dig | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | DigNum$ 1 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Land,Creature.cmcLEY | ForceRevealToController$ True | PromptToSkipOptionalAbility$ True | References$ Y | AILogic$ AlwaysConfirm | OptionalAbilityPrompt$ Would you like to put the permanent onto the battlefield? | DestinationZone$ Battlefield | LibraryPosition2$ 0 | SpellDescription$ Look at the top card of your library. If it's a land card or a creature card with converted mana cost less than or equal to the number of loyalty counters on Nissa, Steward of Elements, you may put that card onto the battlefield. A:AB$ Dig | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | DigNum$ 1 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Land,Creature.cmcLEY | ForceRevealToController$ True | PromptToSkipOptionalAbility$ True | References$ Y | AILogic$ AlwaysConfirm | OptionalAbilityPrompt$ Would you like to put the permanent onto the battlefield? | DestinationZone$ Battlefield | LibraryPosition2$ 0 | SpellDescription$ Look at the top card of your library. If it's a land card or a creature card with converted mana cost less than or equal to the number of loyalty counters on Nissa, Steward of Elements, you may put that card onto the battlefield.
......
Name:Stolen Strategy Name:Stolen Strategy
ManaCost:4 R ManaCost:4 R
Types:Enchantment Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your upkeep, exile the top card of each opponent’s library. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your upkeep, exile the top card of each opponent’s library. Until end of turn, you may cast nonland cards from among those exiled cards, and you may spend mana as though it were mana of any color to cast those spells.
SVar:TrigExile:DB$ Mill | Defined$ Player.Opponent | NumCards$ 1 | Destination$ Exile | RememberMilled$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top card of each opponent's library. Until end of turn, you may cast nonland cards and you may spend mana as though it were mana of any color to cast those spells. SVar:TrigExile:DB$ Mill | Defined$ Player.Opponent | NumCards$ 1 | Destination$ Exile | RememberMilled$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top card of each opponent's library. Until end of turn, you may cast nonland cards and you may spend mana as though it were mana of any color to cast those spells.
SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | Triggers$ TriggerCastDoM | SVars$ TrigRemoveSelf | RememberObjects$ Remembered | SubAbility$ DBCleanup SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | Triggers$ TriggerCastDoM | SVars$ TrigRemoveSelf | RememberObjects$ Remembered | SubAbility$ DBCleanup
SVar:STPlay:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonLand | AffectedZone$ Exile | Description$ Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast it. SVar:STPlay:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonLand | AffectedZone$ Exile | Description$ Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast it.
......
Name:Thopter Spy Network Name:Thopter Spy Network
ManaCost:2 U U ManaCost:2 U U
Types:Enchantment Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Artifact.YouCtrl | Execute$ TrigToken | TriggerDescription$ At the beginning of each upkeep, if you control an artifact, create a 1/1 colorless Thopter artifact creature token with flying. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Artifact.YouCtrl | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, if you control an artifact, create a 1/1 colorless Thopter artifact creature token with flying.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_a_thopter_flying | TokenOwner$ You | LegacyImage$ c 1 1 a thopter flying ori SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_1_1_a_thopter_flying | TokenOwner$ You | LegacyImage$ c 1 1 a thopter flying ori
T:Mode$ DamageDoneOnce | CombatDamage$ True | ValidSource$ Creature.Artifact+YouCtrl | TriggerZones$ Battlefield | ValidTarget$ Player | Execute$ TrigDraw | TriggerDescription$ Whenever one or more artifact creatures you control deal combat damage to a player, draw a card. T:Mode$ DamageDoneOnce | CombatDamage$ True | ValidSource$ Creature.Artifact+YouCtrl | TriggerZones$ Battlefield | ValidTarget$ Player | Execute$ TrigDraw | TriggerDescription$ Whenever one or more artifact creatures you control deal combat damage to a player, draw a card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1 SVar:TrigDraw:DB$ Draw | NumCards$ 1
DeckHas:Ability$Token DeckHas:Ability$Token
SVar:Picture:http://www.wizards.com/global/images/magic/general/thopter_spy_network.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/thopter_spy_network.jpg
Oracle:At the beginning of each upkeep, if you control an artifact, create a 1/1 colorless Thopter artifact creature token with flying.\nWhenever one or more artifact creatures you control deal combat damage to a player, draw a card. Oracle:At the beginning of your upkeep, if you control an artifact, create a 1/1 colorless Thopter artifact creature token with flying.\nWhenever one or more artifact creatures you control deal combat damage to a player, draw a card.
...@@ -2,7 +2,8 @@ Name:Yanling's Harbinger ...@@ -2,7 +2,8 @@ Name:Yanling's Harbinger
ManaCost:3 U U ManaCost:3 U U
Types:Creature Bird Types:Creature Bird
PT:2/4 PT:2/4
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Mu Yanling, Celestial Wind, reveal it, and put it into your hand. If you search your library this way, shuffle it. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library and/or graveyard for a card named Mu Yanling, Celestial Wind, reveal it, and put it into your hand. If you search your library this way, shuffle it.
SVar:TrigSearch:DB$ ChangeZone | Origin$ Library,Graveyard | Destination$ Hand | ChangeType$ Card.namedMu Yanling; Celestial Wind | ChangeNum$ 1 | Optional$ True SVar:TrigSearch:DB$ ChangeZone | Origin$ Library,Graveyard | Destination$ Hand | ChangeType$ Card.namedMu Yanling; Celestial Wind | ChangeNum$ 1 | Optional$ True
DeckHints:Name$Mu Yanling, Celestial Wind DeckHints:Name$Mu Yanling, Celestial Wind
Oracle:When Yanling's Harbinger enters the battlefield, you may search your library and/or graveyard for a card named Mu Yanling, Celestial Wind, reveal it, and put it into your hand. If you search your library this way, shuffle it. Oracle:Flying\nWhen Yanling's Harbinger enters the battlefield, you may search your library and/or graveyard for a card named Mu Yanling, Celestial Wind, reveal it, and put it into your hand. If you search your library this way, shuffle it.
Perilous Vault Animist's Awakening
Archangel of Thune Bag of Holding
Soul of Zendikar
Boundless Realms Boundless Realms
Malakir Cullblade Crash of Rhino Beetles
Nissa's Expedition Creeping Trailblazer
Crop Rotation
Crystalline Crawler
Dismiss into Dream Dismiss into Dream
Elemental Bond Elemental Bond
Elvish Archdruid Elvish Archdruid
Elvish Mystic Elvish Mystic
Nahiri, the Lithomancer
Felidar Umbra Felidar Umbra
Indrik Umbra Indrik Umbra
Infernal Reckoning
Into the Wilds Into the Wilds
Joraga Invocation Joraga Invocation
Malakir Cullblade
Might of the Masses
Mind Control Mind Control
Nahiri, the Lithomancer
Nesting Dragon
Nissa's Expedition
Nissa's Pilgrimage Nissa's Pilgrimage
Nissa's Revelation Nissa's Revelation
Nissa, Vastwood Seer Nissa, Vastwood Seer
Nissa, Worldwaker Nissa, Worldwaker
Ob Nixilis of the Black Oath Ob Nixilis of the Black Oath
Ob Nixilis, Unshackled Ob Nixilis, Unshackled
Omnath, Locus of the Roil
Perilous Vault
Risen Reef