diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java index cc16604b71f..1908453f2d4 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java @@ -66,6 +66,16 @@ public class CountersPutEffect extends SpellAbilityEffect { } stringBuilder.append(pronoun ? "they" : who).append(" "); + final String typeName = CounterType.getType(sa.getParam("CounterType")).getName().toLowerCase(); + + final List playerCounters = Arrays.asList("energy", "experience", "poison", "ticket"); + if (playerCounters.contains(typeName)) { + stringBuilder.append(pronoun ? "get " : "gets "); + stringBuilder.append(Lang.nounWithNumeralExceptOne(AbilityUtils.calculateAmount(card, + sa.getParamOrDefault("CounterNum", "1"), sa), typeName + " counter")); + stringBuilder.append("."); + return stringBuilder.toString(); + } String desc = sa.getDescription(); boolean forEach = desc.contains("for each"); @@ -105,7 +115,6 @@ public class CountersPutEffect extends SpellAbilityEffect { stringBuilder.append("up to "); } - final String typeName = CounterType.getType(sa.getParam("CounterType")).getName().toLowerCase(); stringBuilder.append(Lang.nounWithNumeralExceptOne(amount, typeName + " counter")); stringBuilder.append(divAsChoose || divRandom ? " among " : " on "); diff --git a/forge-game/src/main/java/forge/game/card/CounterEnumType.java b/forge-game/src/main/java/forge/game/card/CounterEnumType.java index b1b8a302b3d..16d43b010c5 100644 --- a/forge-game/src/main/java/forge/game/card/CounterEnumType.java +++ b/forge-game/src/main/java/forge/game/card/CounterEnumType.java @@ -385,6 +385,8 @@ public enum CounterEnumType { POISON("POISN"), + TICKET("TICKET"), + // Keyword Counters /* FLYING("Flying"), diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java index 4df43e21a2c..8ad53a1993e 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java @@ -79,6 +79,7 @@ public class VField implements IVDoc { private final FLabel lblPoison = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).icon(FSkin.getImage(FSkinProp.IMG_ZONE_POISON)).iconInBackground().build(); private final FLabel lblEnergy = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).icon(FSkin.getImage(FSkinProp.IMG_ENERGY)).iconInBackground().build(); private final FLabel lblExperience = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).icon(FSkin.getImage(FSkinProp.IMG_EXPERIENCE)).iconInBackground().build(); + private final FLabel lblTicket = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).icon(FSkin.getImage(FSkinProp.IMG_TICKET)).iconInBackground().build(); private final PhaseIndicator phaseIndicator = new PhaseIndicator(); @@ -113,6 +114,7 @@ public class VField implements IVDoc { lblPoison.setFocusable(false); lblEnergy.setFocusable(false); lblExperience.setFocusable(false); + lblTicket.setFocusable(false); avatarArea.setOpaque(false); avatarArea.setBackground(FSkin.getColor(FSkin.Colors.CLR_HOVER)); @@ -215,12 +217,29 @@ public class VField implements IVDoc { detailsPanel.updateZones(); } - private void addLblExperience() { - if (lblExperience.isShowing() || lblEnergy.isShowing()) { - return; // energy takes precedence + private void addLblTicket() { + if (lblTicket.isShowing() || lblExperience.isShowing() || lblEnergy.isShowing() || lblPoison.isShowing()) { + return; // experience, energy, poison take precedence } - if (lblExperience.isShowing() || lblPoison.isShowing()) { - return; // poison takes precedence + avatarArea.remove(lblLife); + lblLife.setIcon(FSkin.getImage(FSkinProp.ICO_QUEST_LIFE)); + avatarArea.add(lblLife, "w 50%!, h 20px!, split 2"); + avatarArea.add(lblTicket, "w 50%!, h 20px!, wrap"); + } + + private void removeLblTicket() { + if (!lblTicket.isShowing()) { + return; + } + avatarArea.remove(lblTicket); + avatarArea.remove(lblLife); + avatarArea.add(lblLife, "w 100%!, h 20px!, wrap"); + } + + + private void addLblExperience() { + if (lblExperience.isShowing() || lblEnergy.isShowing() || lblPoison.isShowing()) { + return; // energy and poison take precedence } avatarArea.remove(lblLife); lblLife.setIcon(FSkin.getImage(FSkinProp.ICO_QUEST_LIFE)); @@ -288,10 +307,12 @@ public class VField implements IVDoc { final int poison = player.getCounters(CounterEnumType.POISON); final int energy = player.getCounters(CounterEnumType.ENERGY); final int experience = player.getCounters(CounterEnumType.EXPERIENCE); + final int ticket = player.getCounters(CounterEnumType.TICKET); if (poison > 0) { removeLblEnergy(); removeLblExperience(); + removeLblTicket(); addLblPoison(); lblPoison.setText(String.valueOf(poison)); if (poison < POISON_CRITICAL) { @@ -305,6 +326,7 @@ public class VField implements IVDoc { if (energy > 0) { removeLblExperience(); + removeLblTicket(); if (poison == 0) { addLblEnergy(); lblEnergy.setText(String.valueOf(energy)); @@ -314,6 +336,7 @@ public class VField implements IVDoc { } if (experience > 0) { + removeLblTicket(); if (poison == 0 && energy == 0) { addLblExperience(); lblExperience.setText(String.valueOf(experience)); @@ -322,6 +345,15 @@ public class VField implements IVDoc { removeLblExperience(); } + if (ticket > 0) { + if (poison == 0 && energy == 0 && experience == 0) { + addLblTicket(); + lblTicket.setText(String.valueOf(ticket)); + } + } else { + removeLblTicket(); + } + final boolean highlighted = isHighlighted(); this.avatarArea.setBorder(highlighted ? borderAvatarHighlighted : borderAvatarSimple ); this.avatarArea.setOpaque(highlighted); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/CardFaceSymbols.java b/forge-gui-desktop/src/main/java/forge/toolbox/CardFaceSymbols.java index 177b7dc24d9..e2bc25d5190 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/CardFaceSymbols.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/CardFaceSymbols.java @@ -99,6 +99,7 @@ public class CardFaceSymbols { MANA_IMAGES.put("T", FSkin.getImage(FSkinProp.IMG_TAP)); MANA_IMAGES.put("Q", FSkin.getImage(FSkinProp.IMG_UNTAP)); MANA_IMAGES.put("E", FSkin.getImage(FSkinProp.IMG_ENERGY, 40, 40)); + MANA_IMAGES.put("TK", FSkin.getImage(FSkinProp.IMG_TICKET, 40, 40)); MANA_IMAGES.put("EXPERIENCE", FSkin.getImage(FSkinProp.IMG_EXPERIENCE, 40, 30)); MANA_IMAGES.put("CHAOS", FSkin.getImage(FSkinProp.IMG_CHAOS)); MANA_IMAGES.put("slash", FSkin.getImage(FSkinProp.IMG_SLASH)); diff --git a/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java b/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java index 59ec12349cf..39e1ac832ea 100644 --- a/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java +++ b/forge-gui-desktop/src/main/java/forge/toolbox/FSkin.java @@ -1463,6 +1463,7 @@ public class FSkin { addEncodingSymbol("S", FSkinProp.IMG_MANA_SNOW); addEncodingSymbol("T", FSkinProp.IMG_TAP); addEncodingSymbol("E", FSkinProp.IMG_ENERGY); + addEncodingSymbol("TK", FSkinProp.IMG_TICKET); addEncodingSymbol("EXPERIENCE", FSkinProp.IMG_EXPERIENCE); addEncodingSymbol("A-", FSkinProp.IMG_ALCHEMY); diff --git a/forge-gui-mobile/src/forge/assets/FSkinImage.java b/forge-gui-mobile/src/forge/assets/FSkinImage.java index aaf90234b9a..9dd891e97e0 100644 --- a/forge-gui-mobile/src/forge/assets/FSkinImage.java +++ b/forge-gui-mobile/src/forge/assets/FSkinImage.java @@ -193,6 +193,7 @@ public enum FSkinImage implements FImage { COUNTERS3 (FSkinProp.IMG_COUNTERS3, SourceFile.ICONS), COUNTERS_MULTI (FSkinProp.IMG_COUNTERS_MULTI, SourceFile.ICONS), ENERGY (FSkinProp.IMG_ENERGY, SourceFile.ICONS), + TICKET (FSkinProp.IMG_TICKET, SourceFile.ICONS), //Dock Icons SHORTCUTS (FSkinProp.ICO_SHORTCUTS, SourceFile.ICONS), diff --git a/forge-gui-mobile/src/forge/assets/TextRenderer.java b/forge-gui-mobile/src/forge/assets/TextRenderer.java index 9f6c4ee4fcd..d25b7b2fbd0 100644 --- a/forge-gui-mobile/src/forge/assets/TextRenderer.java +++ b/forge-gui-mobile/src/forge/assets/TextRenderer.java @@ -72,6 +72,7 @@ public class TextRenderer { Forge.getAssets().symbolLookup().put("S", FSkinImage.MANA_SNOW); Forge.getAssets().symbolLookup().put("T", FSkinImage.TAP); Forge.getAssets().symbolLookup().put("E", FSkinImage.ENERGY); + Forge.getAssets().symbolLookup().put("TK", FSkinImage.TICKET); Forge.getAssets().symbolLookup().put("AE", FSkinImage.AETHER_SHARD); Forge.getAssets().symbolLookup().put("PW", FSkinImage.PW_BADGE_COMMON); Forge.getAssets().symbolLookup().put("CR", FSkinImage.QUEST_COINSTACK); diff --git a/forge-gui-mobile/src/forge/card/CardFaceSymbols.java b/forge-gui-mobile/src/forge/card/CardFaceSymbols.java index cb8cc135829..c33042dcdea 100644 --- a/forge-gui-mobile/src/forge/card/CardFaceSymbols.java +++ b/forge-gui-mobile/src/forge/card/CardFaceSymbols.java @@ -79,6 +79,7 @@ public class CardFaceSymbols { Forge.getAssets().manaImages().put("S", FSkinImage.MANA_SNOW); Forge.getAssets().manaImages().put("T", FSkinImage.TAP); Forge.getAssets().manaImages().put("E", FSkinImage.ENERGY); + Forge.getAssets().manaImages().put("TK", FSkinImage.TICKET); Forge.getAssets().manaImages().put("slash", FSkinImage.SLASH); Forge.getAssets().manaImages().put("attack", FSkinImage.ATTACK); Forge.getAssets().manaImages().put("defend", FSkinImage.DEFEND); diff --git a/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java b/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java index 88181cfce61..ea04c9746f3 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java @@ -467,6 +467,7 @@ public class VPlayerPanel extends FContainer { private int poisonCounters = player.getCounters(CounterEnumType.POISON); private int energyCounters = player.getCounters(CounterEnumType.ENERGY); private int experienceCounters = player.getCounters(CounterEnumType.EXPERIENCE); + private int ticketCounters = player.getCounters(CounterEnumType.TICKET); private String lifeStr = String.valueOf(life); private LifeLabel() { @@ -515,7 +516,7 @@ public class VPlayerPanel extends FContainer { adjustHeight = 1; float divider = Gdx.app.getGraphics().getHeight() > 900 ? 1.2f : 2f; if(Forge.altPlayerLayout && !Forge.altZoneTabs && Forge.isLandscapeMode()) { - if (poisonCounters == 0 && energyCounters == 0 && experienceCounters == 0) { + if (poisonCounters == 0 && energyCounters == 0 && experienceCounters == 0 && ticketCounters ==0) { g.fillRect(Color.DARK_GRAY, 0, 0, INFO2_FONT.getBounds(lifeStr).width+1, INFO2_FONT.getBounds(lifeStr).height+1); g.drawText(lifeStr, INFO2_FONT, getInfoForeColor().getColor(), 0, 0, getWidth(), getHeight(), false, Align.left, false); } else { @@ -544,6 +545,12 @@ public class VPlayerPanel extends FContainer { g.drawText(String.valueOf(experienceCounters), INFO_FONT, getInfoForeColor().getColor(), textStart, (halfHeight*mod)+2, textWidth, halfHeight, false, Align.left, false); mod+=1; } + if (ticketCounters > 0) { + g.fillRect(Color.DARK_GRAY, 0, (halfHeight*mod)+2, INFO_FONT.getBounds(String.valueOf(ticketCounters)).width+halfHeight+1, INFO_FONT.getBounds(String.valueOf(ticketCounters)).height+1); + g.drawImage(FSkinImage.TICKET, 0, (halfHeight*mod)+2, halfHeight, halfHeight); + g.drawText(String.valueOf(ticketCounters), INFO_FONT, getInfoForeColor().getColor(), textStart, (halfHeight*mod)+2, textWidth, halfHeight, false, Align.left, false); + mod+=1; + } adjustHeight = (mod > 2) && (avatar.getHeight() < halfHeight*mod)? mod : 1; } } else { diff --git a/forge-gui/res/cardsfolder/upcoming/blorbian_buddy.txt b/forge-gui/res/cardsfolder/upcoming/blorbian_buddy.txt new file mode 100644 index 00000000000..48ca3becd69 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/blorbian_buddy.txt @@ -0,0 +1,7 @@ +Name:Blorbian Buddy +ManaCost:G +Types:Creature Alien Guest +PT:1/1 +K:Trample +A:AB$ PutCounter | Cost$ G T | Defined$ You | CounterType$ TICKET | AILogic$ AtOppEOT | SpellDescription$ You get {TK} (a ticket counter). +Oracle:Trample\n{G}, {T}: You get {TK} (a ticket counter). diff --git a/forge-gui/res/cardsfolder/upcoming/ticket_turbotubes.txt b/forge-gui/res/cardsfolder/upcoming/ticket_turbotubes.txt new file mode 100644 index 00000000000..9d0debca613 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/ticket_turbotubes.txt @@ -0,0 +1,6 @@ +Name:Ticket Turbotubes +ManaCost:3 +Types:Artifact +A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color. +A:AB$ PutCounter | Cost$ 3 T | Defined$ You | CounterType$ TICKET | AILogic$ AtOppEOT | SpellDescription$ You get {TK} (a ticket counter). +Oracle:{T}: Add one mana of any color.\n{3}, {T}: You get {TK} (a ticket counter). diff --git a/forge-gui/res/lists/TypeLists.txt b/forge-gui/res/lists/TypeLists.txt index 11a4ff8bc3a..0545bc9ac8d 100644 --- a/forge-gui/res/lists/TypeLists.txt +++ b/forge-gui/res/lists/TypeLists.txt @@ -59,6 +59,7 @@ Chimera:Chimeras Citizen:Citizens Clamfolk:Clamfolk Cleric:Clerics +Clown:Clowns Cockatrice:Cockatrices Construct:Constructs Cow:Cows @@ -116,6 +117,7 @@ Gorgon:Gorgons Graveborn:Graveborn Gremlin:Gremlins Griffin:Griffins +Guest:Guests Hag:Hags Halfling:Halflings Hamster:Hamsters diff --git a/forge-gui/res/skins/default/sprite_icons.png b/forge-gui/res/skins/default/sprite_icons.png index 78515f05cdd..6ee3e61146b 100644 Binary files a/forge-gui/res/skins/default/sprite_icons.png and b/forge-gui/res/skins/default/sprite_icons.png differ diff --git a/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java b/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java index d11f53e2268..b529f78ba18 100644 --- a/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java +++ b/forge-gui/src/main/java/forge/localinstance/skin/FSkinProp.java @@ -89,6 +89,7 @@ public enum FSkinProp { IMG_HDZONE_MANAPOOL (new int[] {2, 6, 128, 128}, PropType.BUTTONS), IMG_ZONE_POISON (new int[] {320, 80, 40, 40}, PropType.IMAGE), + IMG_TICKET (new int[] {360, 80, 40, 40}, PropType.IMAGE), //mana images IMG_MANA_B (new int[] {166, 2, 80, 80}, PropType.MANAICONS),