...
 
Commits (50)
......@@ -1339,7 +1339,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
});
for (Card pw : aiPlaneswalkers) {
int curLoyalty = pw.getCounters(CounterType.LOYALTY);
int freshLoyalty = pw.getCurrentState().getBaseLoyalty();
int freshLoyalty = Integer.valueOf(pw.getCurrentState().getBaseLoyalty());
if (freshLoyalty - curLoyalty >= loyaltyDiff && curLoyalty <= maxLoyaltyToConsider) {
return pw;
}
......
......@@ -290,7 +290,6 @@ public class GameCopier {
// TODO: Is this correct? Does it not duplicate keywords from enchantments and such?
for (KeywordInterface kw : c.getHiddenExtrinsicKeywords())
newCard.addHiddenExtrinsicKeyword(kw);
newCard.setExtrinsicKeyword(Lists.newArrayList(c.getExtrinsicKeyword()));
if (c.isTapped()) {
newCard.setTapped(true);
}
......
......@@ -38,7 +38,7 @@ final class CardFace implements ICardFace {
private int iToughness = Integer.MAX_VALUE;
private String power = null;
private String toughness = null;
private int initialLoyalty = -1;
private String initialLoyalty = "";
private String nonAbilityText = null;
private List<String> keywords = null;
......@@ -56,7 +56,7 @@ final class CardFace implements ICardFace {
@Override public int getIntToughness() { return iToughness; }
@Override public String getPower() { return power; }
@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 CardType getType() { return this.type; }
@Override public ManaCost getManaCost() { return this.manaCost; }
......@@ -84,7 +84,7 @@ final class CardFace implements ICardFace {
void setManaCost(ManaCost manaCost0) { this.manaCost = manaCost0; }
void setColor(ColorSet color0) { this.color = color0; }
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) {
final String k[] = value.split("/");
......
......@@ -186,7 +186,7 @@ public final class CardRules implements ICardCharacteristics {
@Override public int getIntToughness() { return mainPart.getIntToughness(); }
@Override public String getPower() { return mainPart.getPower(); }
@Override public String getToughness() { return mainPart.getToughness(); }
@Override public int getInitialLoyalty() { return mainPart.getInitialLoyalty(); }
@Override public String getInitialLoyalty() { return mainPart.getInitialLoyalty(); }
@Override
public String getOracleText() {
......@@ -409,7 +409,7 @@ public final class CardRules implements ICardCharacteristics {
case 'L':
if ("Loyalty".equals(key)) {
this.faces[this.curFace].setInitialLoyalty(Integer.valueOf(value));
this.faces[this.curFace].setInitialLoyalty(value);
}
break;
......
......@@ -12,7 +12,7 @@ public interface ICardCharacteristics {
int getIntToughness();
String getPower();
String getToughness();
int getInitialLoyalty();
String getInitialLoyalty();
String getOracleText();
}
......@@ -376,6 +376,9 @@ public class GameAction {
copied.clearEtbCounters();
}
// update state for view
copied.updateStateForView();
if (fromBattlefield) {
c.setDamage(0); //clear damage after a card leaves the battlefield
c.setHasBeenDealtDeathtouchDamage(false);
......
......@@ -204,7 +204,8 @@ public final class AbilityFactory {
else if (api == ApiType.PermanentCreature || api == ApiType.PermanentNoncreature) {
// If API is a permanent type, and creating AF 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();
}
}
......@@ -389,6 +390,10 @@ public final class AbilityFactory {
sa.setBasicSpell(false);
}
if (mapParams.containsKey("Dash")) {
sa.setDash(true);
}
if (mapParams.containsKey("Outlast")) {
sa.setOutlast(true);
}
......
......@@ -238,7 +238,7 @@ public abstract class SpellAbilityEffect {
}
sb.append(Lang.joinHomogenous(crds));
if (location.equals("Hand")) {
sb.append("to your hand").append(" ");
sb.append(" to your hand");
}
sb.append(" at the ");
if (combat) {
......
......@@ -134,6 +134,9 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
&& !sa.hasParam("Shuffle") && cards.size() >= 2 && !random) {
Player p = AbilityUtils.getDefinedPlayers(source, sa.getParamOrDefault("DefinedPlayer", "You"), sa).get(0);
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) {
......
......@@ -537,10 +537,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
tgtC.getController().getZone(destination), tgtC, sa, null);
if (sa.hasParam("Unearth")) {
movedCard.setUnearthed(true);
movedCard.addExtrinsicKeyword("Haste");
movedCard.addChangedCardKeywords(Lists.newArrayList("Haste"), null, false, false,
game.getNextTimestamp(), true);
registerDelayedTrigger(sa, "Exile", Lists.newArrayList(movedCard));
addLeaveBattlefieldReplacement(movedCard, sa, "Exile");
movedCard.updateStateForView();
}
if (sa.hasParam("FaceDown")) {
movedCard.turnFaceDown(true);
......
......@@ -52,7 +52,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
}
CardCollectionView choices = game.getCardsIn(choiceZone);
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")) {
choices = CardLists.filterControlledBy(choices, tgtPlayers.get(0));
......
......@@ -3,6 +3,8 @@ package forge.game.ability.effects;
import java.util.Arrays;
import java.util.List;
import com.google.common.collect.Lists;
import forge.GameCommand;
import forge.card.mana.ManaCost;
import forge.game.Game;
......@@ -11,6 +13,7 @@ import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.player.Player;
import forge.game.spellability.Ability;
import forge.game.spellability.SpellAbility;
......@@ -35,23 +38,26 @@ public class ControlGainEffect extends SpellAbilityEffect {
if (tgts.isEmpty()) {
sb.append(" (nothing)");
} else {
for (final Card c : getDefinedCards(sa)) {
sb.append(" ");
if (c.isFaceDown()) {
sb.append("Face-down creature (").append(c.getId()).append(')');
} else {
sb.append(c);
}
}
for (final Card c : tgts) {
sb.append(" ");
if (c.isFaceDown()) {
sb.append("Face-down creature (").append(c.getId()).append(')');
} else {
sb.append(c);
}
}
}
sb.append(".");
if (sa.hasParam("Untap")) {
sb.append(" Untap it.");
}
return sb.toString();
}
private static void doLoseControl(final Card c, final Card host,
final boolean tapOnLose, final List<String> addedKeywords,
final long tStamp) {
final boolean tapOnLose, final long tStamp) {
if (null == c || c.hasKeyword("Other players can't gain control of CARDNAME.")) {
return;
}
......@@ -61,12 +67,6 @@ public class ControlGainEffect extends SpellAbilityEffect {
if (tapOnLose) {
c.tap();
}
if (null != addedKeywords) {
for (final String kw : addedKeywords) {
c.removeExtrinsicKeyword(kw);
}
}
} // if
host.removeGainControlTargets(c);
......@@ -82,7 +82,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
final boolean remember = sa.hasParam("RememberControlled");
final boolean forget = sa.hasParam("ForgetControlled");
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<Player> controllers = getDefinedPlayersOrTargeted(sa, "NewController");
......@@ -125,15 +125,22 @@ public class ControlGainEffect extends SpellAbilityEffect {
tgtC.untap();
}
if (null != kws) {
for (final String kw : kws) {
tgtC.addExtrinsicKeyword(kw);
if (kw.equals("Haste")) {
tgtC.updateStateForView(); // ensure that summoning sickness icon is removed
final List<String> kws = Lists.newArrayList();
if (null != keywords) {
for (final String kw : keywords) {
if (kw.startsWith("HIDDEN")) {
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)) {
sa.getHostCard().addRemembered(tgtC);
}
......@@ -143,7 +150,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
}
if (lose != null) {
final GameCommand loseControl = getLoseControlCommand(tgtC, tStamp, bTapOnLose, source, kws);
final GameCommand loseControl = getLoseControlCommand(tgtC, tStamp, bTapOnLose, source);
if (lose.contains("LeavesPlay")) {
sa.getHostCard().addLeavesPlayCommand(loseControl);
}
......@@ -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);
} // end foreach target
}
......@@ -236,14 +263,13 @@ public class ControlGainEffect extends SpellAbilityEffect {
* @return a {@link forge.GameCommand} object.
*/
private static GameCommand getLoseControlCommand(final Card c,
final long tStamp, final boolean bTapOnLose, final Card hostCard,
final List<String> kws) {
final long tStamp, final boolean bTapOnLose, final Card hostCard) {
final GameCommand loseControl = new GameCommand() {
private static final long serialVersionUID = 878543373519872418L;
@Override
public void run() {
doLoseControl(c, hostCard, bTapOnLose, kws, tStamp);
doLoseControl(c, hostCard, bTapOnLose, tStamp);
c.getSVars().remove("SacMe");
}
};
......
......@@ -83,10 +83,6 @@ public class DigEffect extends SpellAbilityEffect {
boolean changeAll = 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.getParam("ChangeNum").equalsIgnoreCase("All")) {
......@@ -307,9 +303,6 @@ public class DigEffect extends SpellAbilityEffect {
else {
c = game.getAction().moveTo(zone, c, sa);
if (destZone1.equals(ZoneType.Battlefield)) {
for (final String kw : keywords) {
c.addExtrinsicKeyword(kw);
}
if (sa.hasParam("Tapped")) {
c.setTapped(true);
}
......@@ -377,11 +370,7 @@ public class DigEffect extends SpellAbilityEffect {
if (!origin.equals(c.getZone().getZoneType())) {
table.put(origin, c.getZone().getZoneType(), c);
}
if (destZone2 == ZoneType.Battlefield && !keywords.isEmpty()) {
for (final String kw : keywords) {
c.addExtrinsicKeyword(kw);
}
} else if (destZone2 == ZoneType.Exile) {
if (destZone2 == ZoneType.Exile) {
if (sa.hasParam("ExileWithCounter")) {
c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")),
1, player, true, counterTable);
......
package forge.game.ability.effects;
import com.google.common.collect.Lists;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.player.Player;
......@@ -25,9 +27,8 @@ public class PermanentEffect extends SpellAbilityEffect {
// some extra for Dashing
if (sa.isDash()) {
c.addExtrinsicKeyword("Haste");
c.setSVar("EndOfTurnLeavePlay", "Dash");
c.updateKeywords();
registerDelayedTrigger(sa, "Hand", Lists.newArrayList(c));
}
}
}
......@@ -94,7 +94,6 @@ public class Card extends GameEntity implements Comparable<Card> {
private final CardDamageHistory damageHistory = new CardDamageHistory();
private Map<Card, Map<CounterType, Integer>> countersAddedBy = Maps.newTreeMap();
private KeywordCollection extrinsicKeyword = new KeywordCollection();
// Hidden keywords won't be displayed on the card
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
......@@ -540,8 +539,7 @@ public class Card extends GameEntity implements Comparable<Card> {
}
public final void updatePowerToughnessForView() {
currentState.getView().updatePower(this);
currentState.getView().updateToughness(this);
view.updateCounters(this);
}
public final void updateTypesForView() {
......@@ -2698,6 +2696,13 @@ public class Card extends GameEntity implements Comparable<Card> {
}
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();
if (lastEntry != null) {
final long lastTimestamp = lastEntry.getKey();
......@@ -3727,7 +3732,6 @@ public class Card extends GameEntity implements Comparable<Card> {
if (!removeIntrinsic) {
keywords.insertAll(state.getIntrinsicKeywords());
}
keywords.insertAll(extrinsicKeyword.getValues());
// see if keyword changes are in effect
for (final KeywordsChange ck : changedCardKeywords.values()) {
......@@ -3755,11 +3759,6 @@ public class Card extends GameEntity implements Comparable<Card> {
return;
}
}
for (KeywordInterface kw : extrinsicKeyword.getValues()) {
if (!visitor.visit(kw)) {
return;
}
}
} else {
for (KeywordInterface kw : getUnhiddenKeywords(state)) {
if (!visitor.visit(kw)) {
......@@ -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
public final List<KeywordInterface> getHiddenExtrinsicKeywords() {
ListKeywordVisitor visitor = new ListKeywordVisitor();
......
......@@ -325,9 +325,6 @@ public class CardFactory {
// ******************************************************************
// ************** Link to different CardFactories *******************
if (card.isPlaneswalker()) {
buildPlaneswalkerAbilities(card);
}
if (state == CardStateName.LeftSplit || state == CardStateName.RightSplit) {
for (final SpellAbility sa : card.getSpellAbilities()) {
......@@ -383,18 +380,6 @@ public class CardFactory {
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) {
final Card card = new Card(cardId, paperCard, game);
......
......@@ -3508,7 +3508,7 @@ public class CardFactoryUtil {
String abExile = "DB$ ChangeZone | Defined$ Self | Origin$ Stack | Destination$ Exile";
String delTrig = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You " +
" | 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
String abPlay = "DB$ Play | Defined$ Self | WithoutManaCost$ True | Optional$ True";
......@@ -3850,23 +3850,11 @@ public class CardFactoryUtil {
inst.addSpellAbility(sa);
} else if (keyword.startsWith("Dash")) {
final String[] k = keyword.split(":");
final String dashString = "SP$ PermanentCreature | Cost$ " + k[1] + " | SubAbility$"
+ " DashDelayedTrigger";
final String dbDelayTrigger = "DB$ DelayedTrigger | Mode$ Phase | Phase$"
+ " 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 String dashString = "SP$ PermanentCreature | Cost$ " + k[1] + " | StackDescription$ CARDNAME (Dash)"
+ " | Dash$ True | NonBasicSpell$ True"
+ " | SpellDescription$ Dash " + ManaCostParser.parse(k[1]) + " (" + inst.getReminderText() + ")";
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.setTemporary(!intrinsic);
......@@ -4527,6 +4515,8 @@ public class CardFactoryUtil {
card.setSVar("CipherTrigger", trig);
card.setSVar("PlayEncoded", ab);
} else if (keyword.startsWith("Dash")) {
effect = "Mode$ Continuous | Affected$ Card.Self+dashed | AddKeyword$ Haste";
} else if (keyword.equals("Devoid")) {
effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" +
" | CharacteristicDefining$ True | SetColor$ Colorless | Secondary$ True" +
......
......@@ -1639,6 +1639,11 @@ public class CardProperty {
return false;
}
return card.getCastSA().isSurged();
} else if (property.startsWith("dashed")) {
if (card.getCastSA() == null) {
return false;
}
return card.getCastSA().isDash();
} else if (property.startsWith("evoked")) {
if (card.getCastSA() == null) {
return false;
......
......@@ -53,7 +53,7 @@ public class CardState extends GameObject {
private byte color = MagicColor.COLORLESS;
private int basePower = 0;
private int baseToughness = 0;
private int baseLoyalty = 0;
private String baseLoyalty = "";
private KeywordCollection intrinsicKeywords = new KeywordCollection();
private final FCollection<SpellAbility> nonManaAbilities = new FCollection<SpellAbility>();
......@@ -72,6 +72,8 @@ public class CardState extends GameObject {
private final CardStateView view;
private final Card card;
private ReplacementEffect loyaltyRep = null;
public CardState(Card card, CardStateName name) {
this(card.getView().createAlternateState(name), card);
}
......@@ -174,11 +176,11 @@ public class CardState extends GameObject {
view.updateToughness(this);
}
public int getBaseLoyalty() {
public String getBaseLoyalty() {
return baseLoyalty;
}
public final void setBaseLoyalty(final int loyalty) {
baseLoyalty = loyalty;
public final void setBaseLoyalty(final String string) {
baseLoyalty = string;
view.updateLoyalty(this);
}
......@@ -400,6 +402,14 @@ public class CardState extends GameObject {
public FCollectionView<ReplacementEffect> getReplacementEffects() {
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);
return result;
}
......
......@@ -255,7 +255,6 @@ public final class CardUtil {
newCopy.setBaseToughness(in.getCurrentToughness() + in.getTempToughnessBoost() + in.getSemiPermanentToughnessBoost());
newCopy.setCounters(Maps.newEnumMap(in.getCounters()));
newCopy.setExtrinsicKeyword(in.getExtrinsicKeyword());
newCopy.setColor(in.determineColor().getColor());
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
......
......@@ -659,6 +659,8 @@ public class CardView extends GameEntityView {
if (c.getGame() != null) {
currentStateView.updateColors(currentState);
}
} else {
currentStateView.updateLoyalty(currentState);
}
currentState.getView().updateKeywords(c, currentState); //update keywords even if state doesn't change
......@@ -685,6 +687,8 @@ public class CardView extends GameEntityView {
if (c.getGame() != null) {
alternateStateView.updateColors(alternateState);
}
} else {
alternateStateView.updateLoyalty(alternateState);
}
alternateState.getView().updateKeywords(c, alternateState);
}
......@@ -889,13 +893,17 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Toughness, c.getBaseToughness());
}
public int getLoyalty() {
public String getLoyalty() {
return get(TrackableProperty.Loyalty);
}
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);
}
void updateLoyalty(CardState c) {
......@@ -911,7 +919,7 @@ public class CardView extends GameEntityView {
return;
}
}
set(TrackableProperty.Loyalty, 0); //alternates don't need loyalty
set(TrackableProperty.Loyalty, "0"); //alternates don't need loyalty
}
public String getSetCode() {
......
......@@ -209,11 +209,10 @@ public class Untap extends Phase {
// Remove temporary keywords
for (final Card c : player.getCardsIn(ZoneType.Battlefield)) {
c.removeAllExtrinsicKeyword("This card doesn't untap during your next untap step.");
c.removeAllExtrinsicKeyword("HIDDEN This card doesn't untap during your next untap step.");
c.removeHiddenExtrinsicKeyword("This card doesn't untap during your next untap step.");
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.addHiddenExtrinsicKeyword("HIDDEN This card doesn't untap during your next untap step.");
c.removeHiddenExtrinsicKeyword("This card doesn't untap during your next two untap steps.");
c.addHiddenExtrinsicKeyword("This card doesn't untap during your next untap step.");
}
}
......
......@@ -77,7 +77,7 @@ public enum TrackableProperty {
RulesText(TrackableTypes.StringType),
Power(TrackableTypes.IntegerType),
Toughness(TrackableTypes.IntegerType),
Loyalty(TrackableTypes.IntegerType),
Loyalty(TrackableTypes.StringType),
ChangedColorWords(TrackableTypes.StringMapType),
ChangedTypes(TrackableTypes.StringMapType),
HasDeathtouch(TrackableTypes.BooleanType),
......
......@@ -28,6 +28,11 @@ public enum CSubmenuDownloaders implements ICDoc {
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() {
@Override public void run() {
new GuiDownloader(new GuiDownloadSetPicturesLQ()).show();
......@@ -80,6 +85,7 @@ public enum CSubmenuDownloaders implements ICDoc {
public void initialize() {
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
view.setDownloadPicsCommand(cmdPicDownload);
view.setDownloadPicsHQCommand(cmdPicDownloadHQ);
view.setDownloadSetPicsCommand(cmdSetDownload);
view.setDownloadQuestImagesCommand(cmdQuestImages);
view.setDownloadAchievementImagesCommand(cmdAchievementImages);
......
......@@ -57,6 +57,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics"));
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 btnDownloadAchievementImages = _makeButton(localizer.getMessage("btnDownloadAchievementImages"));
private final FLabel btnReportBug = _makeButton(localizer.getMessage("btnReportBug"));
......@@ -82,6 +83,9 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
pnlContent.add(btnDownloadPics, constraintsBTN);
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
pnlContent.add(btnDownloadPicsHQ, constraintsBTN);
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPicsHQ")), constraintsLBL);
pnlContent.add(btnDownloadSetPics, constraintsBTN);
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSetPics")), constraintsLBL);
......@@ -159,6 +163,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
}
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 setDownloadQuestImagesCommand(UiCommand command) { btnDownloadQuestImages.setCommand(command); }
public void setDownloadAchievementImagesCommand(UiCommand command) { btnDownloadAchievementImages.setCommand(command); }
......
......@@ -437,7 +437,7 @@ public class VAssignDamage {
}
else if (defender instanceof CardView) { // planeswalker
final CardView pw = (CardView)defender;
lethalDamage = pw.getCurrentState().getLoyalty();
lethalDamage = Integer.valueOf(pw.getCurrentState().getLoyalty());
}
}
else {
......
......@@ -705,7 +705,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
String sPt = "";
if (state.isCreature() && state.isPlaneswalker()) {
sPt = state.getPower() + "/" + state.getToughness() +
" (" + String.valueOf(state.getLoyalty()) + ")";
" (" + state.getLoyalty() + ")";
}
else if (state.isCreature()) {
sPt = state.getPower() + "/" + state.getToughness();
......@@ -714,7 +714,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
sPt = "[" + state.getPower() + "/" + state.getToughness() + "]";
}
else if (state.isPlaneswalker()) {
sPt = String.valueOf(state.getLoyalty());
sPt = state.getLoyalty();
}
ptText.setText(sPt);
}
......
......@@ -462,6 +462,26 @@ public class Forge implements ApplicationListener {
if (keyCode == Keys.SHIFT_LEFT || keyCode == Keys.SHIFT_RIGHT) {
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.isModifierKey(keyCode)) {
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 {
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 cardArtWidth = cardArtHeight * CARD_ART_RATIO;
if (cardArt != null) {
......
......@@ -446,7 +446,7 @@ public class VAssignDamage extends FDialog {
}
else if (defender instanceof CardView) { // planeswalker
CardView pw = (CardView)defender;
lethalDamage = pw.getCurrentState().getLoyalty();
lethalDamage = Integer.valueOf(pw.getCurrentState().getLoyalty());
}
}
else {
......
......@@ -6,6 +6,7 @@ import forge.Graphics;
import forge.MulliganDefs;
import forge.StaticData;
import forge.ai.AiProfileUtil;
import forge.assets.FLanguage;
import forge.assets.FSkin;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont;
......@@ -48,6 +49,14 @@ public class SettingsPage extends TabPage<SettingsScreen> {
lstSettings.addGroup("Sound Options");
//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",
"Sets the theme that determines how display components are skinned.",
FSkin.getAllSkins()) {
......
Name:Chance for Glory
ManaCost:1 R W
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: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
......
......@@ -2,8 +2,8 @@ Name:Cruel Celebrant
ManaCost:W B
Types:Creature Vampire
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$ 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$ 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 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:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
DeckHas:Ability$LifeGain
......
......@@ -5,7 +5,7 @@ PT:5/5
K:Kicker:3
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
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:X:Count$CardPower
SVar:Y:Count$CardToughness
......
Name:Nissa, Steward of Elements
ManaCost:X G U
Types:Legendary Planeswalker Nissa
Loyalty:0
K:etbCounter:LOYALTY:X
Loyalty:X
SVar:X:Count$xPaid
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.
......
Name:Stolen Strategy
ManaCost:4 R
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: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.
......
Name:Thopter Spy Network
ManaCost:2 U U
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
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
DeckHas:Ability$Token
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
ManaCost:3 U U
Types:Creature Bird
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.
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
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
Archangel of Thune
Soul of Zendikar
Animist's Awakening
Bag of Holding
Boundless Realms
Malakir Cullblade
Nissa's Expedition
Crash of Rhino Beetles
Creeping Trailblazer
Crop Rotation
Crystalline Crawler
Dismiss into Dream
Elemental Bond
Elvish Archdruid
Elvish Mystic
Nahiri, the Lithomancer
Felidar Umbra
Indrik Umbra
Infernal Reckoning
Into the Wilds
Joraga Invocation
Malakir Cullblade
Might of the Masses
Mind Control
Nahiri, the Lithomancer
Nesting Dragon
Nissa's Expedition
Nissa's Pilgrimage
Nissa's Revelation
Nissa, Vastwood Seer
Nissa, Worldwaker
Ob Nixilis of the Black Oath
Ob Nixilis, Unshackled
Omnath, Locus of the Roil
Perilous Vault
Risen Reef
Soul of Zendikar
Sword of the Animist
Turntimber Ranger
Vastwood Hydra
Vine Snare
Volcanic Rambler
Wakeroot Elemental
Wild Instincts
Woodborn Behemoth
Yarok's Fenlurker
Yarok's Wavecrasher
Yarok, the Desecrated
Zendikar Incarnate
Zendikar's Roil
\ No newline at end of file
[metadata]
Code=SS2
Date=2019-06-28
Name=Signature Spellbook: Gideon
MciCode=ss2
Type=Reprint
[cards]
1 M Gideon Jura
2 R Martyr's Bond
3 R Path to Exile
4 R Rest in Peace
5 R Shielded by Faith
6 R True Conviction
7 R Worship
8 R Blackblade Reforged
......@@ -3,5 +3,5 @@ Name:Brawl
Order:101
Type:Casual
Subtype:Commander
Sets:XLN, RIX, DOM, M19, G18, GRN, RNA, WAR
Sets:XLN, RIX, DOM, M19, G18, GRN, RNA, WAR, M20
Banned:Sorcerous Spyglass
\ No newline at end of file
......@@ -179,6 +179,7 @@ Achievements=Erfolge
# VSubmenuDownloaders.java
btnDownloadSetPics=Bilder(LQ) Sets herunterladen
btnDownloadPics=Bilder(LQ) Karten herunterladen
btnDownloadPicsHQ=Bilder(HQ) Karten herunterladen (Sehr langsam!)
btnDownloadQuestImages=Bilder für Quests herunterladen
btnDownloadAchievementImages=Bilder für Erfolge herunterladen
btnReportBug=Einen Fehler melden
......@@ -189,6 +190,7 @@ btnHowToPlay=Wie man spielt
btnDownloadPrices=Kartenpreise herunterladen
btnLicensing=Lizenzhinweis
lblDownloadPics=Lädt ein Standardbild pro Karte.
lblDownloadPicsHQ=Lädt ein Standardbild (HQ) pro Karte.
lblDownloadSetPics=Lädt alle Bilder pro Karte. Eines für jedes Set, in welchem die Karte auftauchte.
lblDownloadQuestImages=Lädt die Bilder für den Quest-Modus.
lblDownloadAchievementImages=Lädt die Bilder zu den möglichen Erfolgen. Verschönert die Trophäensammlung.
......@@ -317,7 +319,7 @@ lblIsGoingFirst=beginnt.
lblYouAreGoing=Du startest
lblMulligan=Mulligan
lblDoYouWantToKeepYourHand=Starthand behalten?
lblReturnForLondon=Lege %n Karten unter die Bibliothek
lblReturnForLondon=Lege %d Karten unter die Bibliothek
lblOk=OK
lblReset=Zurück
lblAuto=Auto
......
......@@ -178,6 +178,7 @@ KeyboardShortcuts=Keyboard Shortcuts
Achievements=Achievements
# VSubmenuDownloaders.java
btnDownloadSetPics=Download LQ Set Pictures
btnDownloadPicsHQ=Download HQ Card Pictures (Very Slow!)
btnDownloadPics=Download LQ Card Pictures
btnDownloadQuestImages=Download Quest Images
btnDownloadAchievementImages=Download Achievement Images
......@@ -189,6 +190,7 @@ btnHowToPlay=How To Play
btnDownloadPrices=Download Card Prices
btnLicensing=License Details
lblDownloadPics=Download default card picture for each card.
lblDownloadPicsHQ=Download default card HQ picture for each card.
lblDownloadSetPics=Download all pictures of each card (one for each set the card appeared in)
lblDownloadQuestImages=Download tokens and icons used in Quest mode.
lblDownloadAchievementImages=Download achievement images to really make your trophies stand out.
......@@ -317,7 +319,7 @@ lblIsGoingFirst=is going first
lblYouAreGoing=you are going
lblMulligan=Mulligan
lblDoYouWantToKeepYourHand=Do you want to keep your hand?
lblReturnForLondon=Return %n card(s) to bottom of library
lblReturnForLondon=Return %d card(s) to the bottom of your library
lblOk=Ok
lblReset=Reset
lblAuto=Auto
......
......@@ -179,6 +179,7 @@ Achievements=Logros
# VSubmenuDownloaders.java
btnDownloadSetPics=Descargar todos los Sets de Cartas
btnDownloadPics=Descargar todas las Cartas
btnDownloadPicsHQ=Descargar todas las Cartas en calidad alta (Muy lento!)
btnDownloadQuestImages=Descargar Imágenes del modo Quest
btnDownloadAchievementImages=Descagar Imágenes de los Logros
btnReportBug=Reportar un error
......@@ -189,6 +190,7 @@ btnHowToPlay=Cómo jugar (Inglés)
btnDownloadPrices=Descargar los precios de las cartas
btnLicensing=Detalles de la licencia
lblDownloadPics=Descargar la imagen de la carta por defecto para cada carta.
lblDownloadPicsHQ=Descargar la imagen en calidad alta de la carta por defecto para cada carta.
lblDownloadSetPics=Descargue todas las imágenes de cada carta (una por cada set donde apareció la carta)
lblDownloadQuestImages=Descarga fichas e íconos utilizados en el modo Quest.
lblDownloadAchievementImages=Descarga imágenes de logros para que tus trofeos realmente destaquen.
......@@ -317,7 +319,7 @@ lblIsGoingFirst=va primero
lblYouAreGoing=vas
lblMulligan=Mulligan
lblDoYouWantToKeepYourHand=¿Quieres quedarte tu mano?
lblReturnForLondon=Return %n card(s) to bottom of library
lblReturnForLondon=Return %d card(s) to the bottom of your library
lblOk=Ok
lblReset=Reset
lblAuto=Auto
......
[metadata]
Name:Possibility Storm - Magic Core Set 2020 #03
URL:http://www.possibilitystorm.com/wp-content/uploads/2019/07/122.m203.jpg
Goal:Win
Turns:1
Difficulty:Mythic
Description:Win this turn. Assume your opponent has no mana available.
[state]
humanlife=20
ailife=12
turn=1
activeplayer=human
activephase=MAIN1
humanhand=Shatter;Teferi's Time Twist;Role Reversal;Trumpet Blast
humanbattlefield=Viashino Pyromancer;Retributive Wand;Captain's Hook;Saheeli, Sublime Artificer|Counters:LOYALTY=3;Island;Island;Mountain;Mountain
aibattlefield=Pardic Wanderer
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.download;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.util.ImageUtil;
import java.io.File;
import java.util.*;
public class GuiDownloadPicturesHQ extends GuiDownloadService {
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Set<String> existingSets;
ArrayList<String> existingImages;
@Override
public String getTitle() {
return "Download HQ Card Pictures";
}
@Override
protected final Map<String, String> getNeededFiles() {
File f = new File(ForgeConstants.CACHE_CARD_PICS_DIR);
existingImages = new ArrayList<String>(Arrays.asList(f.list()));
existingSets = retrieveManifestDirectory();
for (final PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
addDLObject(c, false);
if (ImageUtil.hasBackFacePicture(c)) {
addDLObject(c, true);
}
}
for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
addDLObject(c, false);
}
// Add missing tokens to the list of things to download.
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
return downloads;
}
private void addDLObject(final PaperCard c, final boolean backFace) {
final String imageKey = ImageUtil.getImageKey(c, backFace, false);
final String destPath = ForgeConstants.CACHE_CARD_PICS_DIR + imageKey + ".jpg";
if (existingImages.contains(imageKey + ".jpg")) {
return;
}
if (downloads.containsKey(destPath)) {
return;
}
String setCode = c.getEdition();
String cardname = imageKey.replace(".full", "");
switch(setCode) {
case "CFX": setCode="CON"; break;
case "COM": setCode="CMD"; break;
case "FVE": setCode="V09"; break;
case "FVL": setCode="V11"; break;
case "FVR": setCode="V10"; break;
case "MED": setCode="ME1"; break;
case "MPS_AKH": setCode="AKH"; break;
case "MPS_KLD": setCode="MPS"; break;
case "MPS_RNA": setCode="MED"; break;
case "PDS": setCode="H09"; break;
case "PO2": setCode="P02"; break;
case "UGF": setCode="UGIN"; break;
}
setCode = getManualCode(cardname, setCode);
cardname = cardname.replace(" ", "+");
cardname = cardname.replace("'", "");
String scryfallurl = ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + "named?fuzzy=" + cardname;
if(!setCode.equals("???")) scryfallurl += "&set=" + setCode.toLowerCase();
if(backFace) scryfallurl += "&face=back";
scryfallurl += "&format=image";
downloads.put(destPath, scryfallurl);
}
private String getManualCode(String cardname, String originalSetCode) {
String setCode=originalSetCode;
switch(cardname) {
case "Daretti, Ingenious Iconoclast":
case "Elspeth, Knight-Errant":
case "Garruk, Apex Predator":
case "Jace, the Mind Sculptor":
case "Liliana, the Last Hope":
case "Nahiri, the Harbinger":
case "Nicol Bolas, Planeswalker":
case "Sarkhan Unbroken":
case "Teferi, Hero of Dominaria":