diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index b1ae887b9a5..327d21c3f4a 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -667,6 +667,7 @@ public class Card extends GameEntity implements Comparable { } facedown = false; + updateStateForView(); //fixes cards with backside viewable // need to run faceup commands, currently // it does cleanup the modified facedown state if (result) { diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index 9a025e20f0d..47c5d8211b7 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -339,7 +339,6 @@ public final class CardUtil { //show hidden if exiled facedown ret.setImageKey(ImageKeys.getTokenKey(c.isInZone(ZoneType.Exile) ? ImageKeys.HIDDEN_CARD : ImageKeys.MORPH_IMAGE)); - //TODO: the imagey key here don't support cards with backside... hmmm cards with backside and hidden should display its faceup verion not their alternate... return ret; } diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 57ba9fa06db..d753c8acdcf 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -134,6 +134,18 @@ public class CardView extends GameEntityView { return get(TrackableProperty.SplitCard); } + public boolean isDoubleFacedCard() { + return get(TrackableProperty.DoubleFaced); + } + + public boolean isAdventureCard() { + return get(TrackableProperty.Adventure); + } + + public boolean isModalCard() { + return get(TrackableProperty.Modal); + } + /* public boolean isTransformed() { return getCurrentState().getState() == CardStateName.Transformed; @@ -678,6 +690,12 @@ public class CardView extends GameEntityView { public CardStateView getAlternateState() { return get(TrackableProperty.AlternateState); } + + public boolean hasBackSide() { + return get(TrackableProperty.HasBackSide); + } + public String getBackSideName() { return get(TrackableProperty.BackSideName); } + CardStateView createAlternateState(final CardStateName state0) { return new CardStateView(getId(), state0, tracker); } @@ -685,6 +703,10 @@ public class CardView extends GameEntityView { public CardStateView getState(final boolean alternate0) { return alternate0 ? getAlternateState() : getCurrentState(); } + void updateBackSide(String stateName, boolean hasBackSide) { + set(TrackableProperty.HasBackSide, hasBackSide); + set(TrackableProperty.BackSideName, stateName); + } void updateState(Card c) { updateName(c); updateDamage(c); @@ -694,6 +716,13 @@ public class CardView extends GameEntityView { set(TrackableProperty.SplitCard, isSplitCard); set(TrackableProperty.FlipCard, c.isFlipCard()); set(TrackableProperty.Facedown, c.isFaceDown()); + set(TrackableProperty.Adventure, c.isAdventureCard()); + set(TrackableProperty.DoubleFaced, c.isDoubleFaced()); + set(TrackableProperty.Modal, c.isModal()); + + //backside + if (c.getAlternateState()!=null) + updateBackSide(c.getAlternateState().getName(), c.hasBackSide()); final Card cloner = c.getCloner(); @@ -733,6 +762,9 @@ public class CardView extends GameEntityView { alternateState = c.getState(CardStateName.Original); } + if (c.hasBackSide() && isFaceDown()) //fixes facedown cards with backside... + alternateState = c.getState(CardStateName.Original); + if (alternateState == null) { set(TrackableProperty.AlternateState, null); } diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index 8d09ad364df..99228d48b56 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -25,6 +25,9 @@ public enum TrackableProperty { Flipped(TrackableTypes.BooleanType), Facedown(TrackableTypes.BooleanType), + Modal(TrackableTypes.BooleanType), + Adventure(TrackableTypes.BooleanType), + DoubleFaced(TrackableTypes.BooleanType), //TODO? Cloner(TrackableTypes.StringType), @@ -164,6 +167,10 @@ public enum TrackableProperty { CanPlay(TrackableTypes.BooleanType), PromptIfOnlyPossibleAbility(TrackableTypes.BooleanType), + //HasBackSide + BackSideName(TrackableTypes.StringType), + HasBackSide(TrackableTypes.BooleanType), + //StackItem Key(TrackableTypes.StringType), SourceTrigger(TrackableTypes.IntegerType), diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 1dcb5140997..e42bff76442 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -336,7 +336,17 @@ public class CardImageRenderer { public static void drawZoom(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h, float dispW, float dispH, boolean isCurrentCard) { boolean canshow = MatchController.instance.mayView(card); - final Texture image = ImageCache.getImage(card.getState(altState).getImageKey(), true); + Texture image = null; + try { + image = ImageCache.getImage(card.getState(altState).getImageKey(), true); + } catch (Exception ex) { + //System.err.println(card.toString()+" : " +ex.getMessage()); + //TODO: don't know why this is needed, needs further investigation... + if (!card.hasAlternateState()) { + altState = false; + image = ImageCache.getImage(card.getState(altState).getImageKey(), true); + } + } FImage sleeves = MatchController.getPlayerSleeve(card.getOwner()); if (image == null) { //draw details if can't draw zoom drawDetails(g, card, gameView, altState, x, y, w, h); diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index 8f8ede1074d..2953bf9f89d 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -485,9 +485,12 @@ public class CardRenderer { } } public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate) { + drawCard(g, card, x, y, w, h, pos, rotate, false); + } + public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean rotate, boolean showAltState) { boolean canshow = MatchController.instance.mayView(card); boolean showsleeves = card.isFaceDown() && card.isInZone(EnumSet.of(ZoneType.Exile)); //fix facedown card image ie gonti lord of luxury - Texture image = new RendererCachedCardImage(card, false).getImage(card.getCurrentState().getImageKey()); + Texture image = new RendererCachedCardImage(card, false).getImage( showAltState ? card.getAlternateState().getImageKey() : card.getCurrentState().getImageKey()); FImage sleeves = MatchController.getPlayerSleeve(card.getOwner()); float radius = (h - w)/8; float croppedArea = isModernFrame(card) ? CROP_MULTIPLIER : 0.97f; @@ -540,15 +543,15 @@ public class CardRenderer { } public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) { - drawCardWithOverlays(g, card, x, y, w, h, pos, false); + drawCardWithOverlays(g, card, x, y, w, h, pos, false, false); } - public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean stackview) { + public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos, boolean stackview, boolean showAltState) { boolean canShow = MatchController.instance.mayView(card); float oldAlpha = g.getfloatAlphaComposite(); boolean unselectable = !MatchController.instance.isSelectable(card) && MatchController.instance.isSelecting(); float cx, cy, cw, ch; cx = x; cy = y; cw = w; ch = h; - drawCard(g, card, x, y, w, h, pos, false); + drawCard(g, card, x, y, w, h, pos, false, showAltState); float padding = w * PADDING_MULTIPLIER; //adjust for card border x += padding; @@ -557,7 +560,7 @@ public class CardRenderer { h -= 2 * padding; // TODO: A hacky workaround is currently used to make the game not leak the color information for Morph cards. - final CardStateView details = card.getCurrentState(); + final CardStateView details = showAltState ? card.getAlternateState() : card.getCurrentState(); final boolean isFaceDown = card.isFaceDown(); final DetailColors borderColor = isFaceDown ? CardDetailUtil.DetailColors.FACE_DOWN : CardDetailUtil.getBorderColor(details, canShow); // canShow doesn't work here for face down Morphs Color color = FSkinColor.fromRGB(borderColor.r, borderColor.g, borderColor.b); @@ -934,7 +937,7 @@ public class CardRenderer { } } else { - drawManaCost(g, card.getCurrentState().getManaCost(), x - padding, y, w + 2 * padding, h, manaSymbolSize); + drawManaCost(g, showAltState ? card.getAlternateState().getManaCost() : card.getCurrentState().getManaCost(), x - padding, y, w + 2 * padding, h, manaSymbolSize); } } } diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index a32af97b9d7..bd77c7618f0 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -46,10 +46,15 @@ public class CardZoom extends FOverlay { private static String currentActivateAction; private static Rectangle flipIconBounds; private static boolean showAltState; + private static boolean showBackSide = false; public static void show(Object item) { + show(item, false); + } + public static void show(Object item, boolean showbackside) { List items0 = new ArrayList<>(); items0.add(item); + showBackSide = showbackside; //reverse the displayed zoomed card for the choice list show(items0, 0, null); } public static void show(FCollectionView items0, int currentIndex0, ActivateHandler activateHandler0) { @@ -158,10 +163,15 @@ public class CardZoom extends FOverlay { @Override public boolean tap(float x, float y, int count) { if (flipIconBounds != null && flipIconBounds.contains(x, y)) { - showAltState = !showAltState; + if (!showBackSide) + showAltState = !showAltState; + else + showBackSide = !showBackSide; return true; } hide(); + showBackSide = false; + showAltState = false; return true; } @@ -169,14 +179,20 @@ public class CardZoom extends FOverlay { public boolean fling(float velocityX, float velocityY) { if (Math.abs(velocityX) > Math.abs(velocityY)) { incrementCard(velocityX > 0 ? -1 : 1); + showBackSide = false; + showAltState = false; return true; } if (velocityY > 0) { zoomMode = !zoomMode; + showBackSide = false; + showAltState = false; return true; } if (currentActivateAction != null && activateHandler != null) { hide(); + showBackSide = false; + showAltState = false; activateHandler.activate(currentIndex); return true; } @@ -282,10 +298,9 @@ public class CardZoom extends FOverlay { float x = (w - cardWidth) / 2; y = (h - cardHeight) / 2; if (zoomMode) { - CardImageRenderer.drawZoom(g, currentCard, gameView, showAltState, x, y, cardWidth, cardHeight, getWidth(), getHeight(), true); - } - else { - CardImageRenderer.drawDetails(g, currentCard, gameView, showAltState, x, y, cardWidth, cardHeight); + CardImageRenderer.drawZoom(g, currentCard, gameView, showBackSide? showBackSide : showAltState, x, y, cardWidth, cardHeight, getWidth(), getHeight(), true); + } else { + CardImageRenderer.drawDetails(g, currentCard, gameView, showBackSide? showBackSide : showAltState, x, y, cardWidth, cardHeight); } if (flipIconBounds != null) { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VStack.java b/forge-gui-mobile/src/forge/screens/match/views/VStack.java index 567665e69bd..b3ae6edd666 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VStack.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VStack.java @@ -382,7 +382,7 @@ public class VStack extends FDropDown { x += PADDING; y += PADDING; - CardRenderer.drawCardWithOverlays(g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top, true); + CardRenderer.drawCardWithOverlays(g, stackInstance.getSourceCard(), x, y, CARD_WIDTH, CARD_HEIGHT, CardStackPosition.Top, true, false); x += CARD_WIDTH + PADDING; w -= x + PADDING - BORDER_THICKNESS; diff --git a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java index 770736b177e..96e19487634 100644 --- a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java +++ b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java @@ -367,6 +367,24 @@ public class FChoiceList extends FList implements ActivateHandler { g.drawText(getChoiceText(value), font, foreColor, x, y, w, h, false, Align.center, true); } } + //simple check for cardview needed on some special renderer for cards + private boolean showAlternate(CardView cardView, String value){ + boolean showAlt = false; + if(cardView.hasAlternateState()){ + if(cardView.hasBackSide()) + showAlt = value.contains(cardView.getBackSideName()); + else if (cardView.isAdventureCard()) + showAlt = value.equals(cardView.getAlternateState().getAbilityText()); + else if (cardView.isSplitCard()) { + //special case if aftermath cards can be cast from graveyard like yawgmoths will, you will have choices + if (cardView.getAlternateState().getOracleText().contains("Aftermath")) + showAlt = cardView.getAlternateState().getOracleText().contains(value); + else + showAlt = value.equals(cardView.getAlternateState().getAbilityText()); + } + } + return showAlt; + } //special renderer for cards protected class PaperCardItemRenderer extends ItemRenderer { @Override @@ -464,7 +482,8 @@ public class FChoiceList extends FList implements ActivateHandler { @Override public boolean tap(Integer index, T value, float x, float y, int count) { if (x <= VStack.CARD_WIDTH + 2 * FList.PADDING) { - CardZoom.show(((IHasCardView)value).getCardView()); + CardView cv = ((IHasCardView)value).getCardView(); + CardZoom.show(cv, showAlternate(cv, value.toString())); return true; } return false; @@ -472,13 +491,16 @@ public class FChoiceList extends FList implements ActivateHandler { @Override public boolean longPress(Integer index, T value, float x, float y) { - CardZoom.show(((IHasCardView)value).getCardView()); + CardView cv = ((IHasCardView)value).getCardView(); + CardZoom.show(cv, showAlternate(cv, value.toString())); return true; } @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { - CardRenderer.drawCardWithOverlays(g, ((IHasCardView)value).getCardView(), x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top); + CardView cv = ((IHasCardView)value).getCardView(); + boolean showAlternate = showAlternate(cv, value.toString()); + CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate); float dx = VStack.CARD_WIDTH + FList.PADDING; x += dx; diff --git a/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java b/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java index 7ff830776ad..3421238909d 100644 --- a/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java +++ b/forge-gui/src/main/java/forge/quest/MainWorldEventDuelManager.java @@ -1,6 +1,5 @@ package forge.quest; -import java.awt.image.renderable.RenderableImage; import java.io.File; import java.util.ArrayList; import java.util.Arrays;