From b5aa3b429e8480aeb962ea3ff65ecd716f174eca Mon Sep 17 00:00:00 2001 From: drdev Date: Sun, 21 Sep 2014 15:22:59 +0000 Subject: [PATCH] Commit first set of alternate win achievements --- .gitattributes | 1 + .../main/java/forge/game/player/Player.java | 13 +++ .../home/settings/VSubmenuAchievements.java | 4 +- .../screens/settings/AchievementsPage.java | 6 +- .../java/forge/achievement/Achievement.java | 22 ++--- .../achievement/AchievementCollection.java | 19 +++-- .../forge/achievement/AltWinAchievements.java | 81 +++++++++++++++++++ .../achievement/ConstructedAchievements.java | 7 +- .../java/forge/achievement/DeckedOut.java | 2 +- .../forge/achievement/DraftAchievements.java | 7 +- .../main/java/forge/achievement/Overkill.java | 2 +- .../main/java/forge/achievement/Poisoned.java | 2 +- .../forge/achievement/QuestAchievements.java | 7 +- .../forge/achievement/SealedAchievements.java | 7 +- .../java/forge/player/GamePlayerUtil.java | 12 +++ .../forge/player/PlayerControllerHuman.java | 4 +- 16 files changed, 138 insertions(+), 58 deletions(-) create mode 100644 forge-gui/src/main/java/forge/achievement/AltWinAchievements.java diff --git a/.gitattributes b/.gitattributes index 2b14a590a24..92aa0ac8185 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16885,6 +16885,7 @@ forge-gui/src/main/java/forge/GuiBase.java -text forge-gui/src/main/java/forge/UiCommand.java svneol=native#text/plain forge-gui/src/main/java/forge/achievement/Achievement.java -text forge-gui/src/main/java/forge/achievement/AchievementCollection.java -text +forge-gui/src/main/java/forge/achievement/AltWinAchievements.java -text forge-gui/src/main/java/forge/achievement/Blackjack.java -text forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java -text forge-gui/src/main/java/forge/achievement/DeckedOut.java -text diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index b240eb23f73..1ba380b1643 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -322,6 +322,19 @@ public class Player extends GameEntity implements Comparable { return result; } + //get single opponent for player if only one, otherwise returns null + //meant to be used after game ends for the sake of achievements + public Player getSingleOpponent() { + if (game.getRegisteredPlayers().size() == 2) { + for (Player p : game.getRegisteredPlayers()) { + if (p.isOpponentOf(this)) { + return p; + } + } + } + return null; + } + /** * Find the smallest life total amongst this player's opponents. * diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java index 7a3ce87e8b9..c69f80b7594 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuAchievements.java @@ -398,12 +398,12 @@ public enum VSubmenuAchievements implements IVSubmenu { } y += PADDING; if (sharedDesc != null) { - g2d.drawString(sharedDesc + "...", x, y); + g2d.drawString(selectedAchievement.isSpecial() ? sharedDesc : sharedDesc + "...", x, y); y += descHeight; } if (mythicDesc != null) { FSkin.setGraphicsColor(g2d, selectedAchievement.earnedMythic() ? TEXT_COLOR : NOT_EARNED_COLOR); - g2d.drawString("(Mythic) " + mythicDesc, x, y); + g2d.drawString(selectedAchievement.isSpecial() ? mythicDesc : "(Mythic) " + mythicDesc, x, y); //handle flavor text here too y += descHeight; } if (rareDesc != null) { diff --git a/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java b/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java index 6a3c5c74981..cdf01365443 100644 --- a/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/AchievementsPage.java @@ -306,13 +306,13 @@ public class AchievementsPage extends TabPage { } y += PADDING; if (sharedDesc != null) { - g.drawText(sharedDesc + "...", DESC_FONT, TEXT_COLOR, + g.drawText(selectedAchievement.isSpecial() ? sharedDesc : sharedDesc + "...", DESC_FONT, TEXT_COLOR, x, y, w, h, false, HAlignment.LEFT, false); y += DESC_FONT.getLineHeight(); } if (mythicDesc != null) { - g.drawText("(Mythic) " + mythicDesc, DESC_FONT, - selectedAchievement.earnedRare() ? TEXT_COLOR : NOT_EARNED_COLOR, + g.drawText(selectedAchievement.isSpecial() ? mythicDesc : "(Mythic) " + mythicDesc, DESC_FONT, //handle flavor text here too + selectedAchievement.earnedMythic() ? TEXT_COLOR : NOT_EARNED_COLOR, x, y, w, h, false, HAlignment.LEFT, false); y += DESC_FONT.getLineHeight(); } diff --git a/forge-gui/src/main/java/forge/achievement/Achievement.java b/forge-gui/src/main/java/forge/achievement/Achievement.java index 408c4f526a3..5262d8012b1 100644 --- a/forge-gui/src/main/java/forge/achievement/Achievement.java +++ b/forge-gui/src/main/java/forge/achievement/Achievement.java @@ -18,8 +18,8 @@ public abstract class Achievement { protected int best, current; //use this constructor for special achievements without tiers - protected Achievement(String displayName0, String description0, FSkinProp overlayImage0) { - this(displayName0, description0, null, 1, null, 1, null, 1, null, 1, overlayImage0); + protected Achievement(String displayName0, String description0, String flavorText0, FSkinProp overlayImage0) { + this(displayName0, description0, null, 1, null, 1, null, 1, "(" + flavorText0 + ")", 1, overlayImage0); //pass flavor text as mythic description so it appears below description faded out } //use this constructor for regular tiered achievements protected Achievement(String displayName0, String sharedDesc0, @@ -39,7 +39,7 @@ public abstract class Achievement { mythicDesc = mythicDesc0; mythicThreshold = mythicThreshold0; overlayImage = overlayImage0; - checkGreaterThan = rareThreshold0 > uncommonThreshold0; + checkGreaterThan = rareThreshold0 >= uncommonThreshold0; } public String getDisplayName() { @@ -66,8 +66,11 @@ public abstract class Achievement { } return image; } + public boolean isSpecial() { + return mythicThreshold == commonThreshold; + } private boolean earnedSpecial() { - return (mythicThreshold == commonThreshold && best > 1); + return (isSpecial() && best > 0); } public boolean earnedMythic() { if (checkGreaterThan) { @@ -96,17 +99,6 @@ public abstract class Achievement { protected abstract int evaluate(Player player, Game game); - protected Player getSingleOpponent(Player player) { - if (player.getGame().getRegisteredPlayers().size() == 2) { - for (Player p : player.getGame().getRegisteredPlayers()) { - if (p.isOpponentOf(player)) { - return p; - } - } - } - return null; - } - private void updateTrophyImage() { FSkinProp background; float opacity = 1; diff --git a/forge-gui/src/main/java/forge/achievement/AchievementCollection.java b/forge-gui/src/main/java/forge/achievement/AchievementCollection.java index 4d5c875f63e..5d5bb487608 100644 --- a/forge-gui/src/main/java/forge/achievement/AchievementCollection.java +++ b/forge-gui/src/main/java/forge/achievement/AchievementCollection.java @@ -24,9 +24,9 @@ import forge.util.FileUtil; import forge.util.XmlUtil; public abstract class AchievementCollection implements Iterable { - private final Map achievements = new LinkedHashMap(); - private final String name, filename; - private final boolean isLimitedFormat; + protected final Map achievements = new LinkedHashMap(); + protected final String name, filename; + protected final boolean isLimitedFormat; static { FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR); @@ -37,19 +37,19 @@ public abstract class AchievementCollection implements Iterable { cb.addItem(FModel.getAchievements(GameType.Draft)); cb.addItem(FModel.getAchievements(GameType.Sealed)); cb.addItem(FModel.getAchievements(GameType.Quest)); + cb.addItem(AltWinAchievements.instance); } protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) { name = name0; filename = filename0; isLimitedFormat = isLimitedFormat0; - buildTopShelf(); - buildCoreShelves(); - buildBottomShelf(); + addSharedAchivements(); + addAchievements(); load(); } - private void buildCoreShelves() { + protected void addSharedAchivements() { add("GameWinStreak", new GameWinStreak(10, 25, 50, 100)); add("MatchWinStreak", new MatchWinStreak(10, 25, 50, 100)); add("TotalGameWins", new TotalGameWins(250, 500, 1000, 2000)); @@ -65,8 +65,7 @@ public abstract class AchievementCollection implements Iterable { add("Hellbent", new Hellbent()); } - protected abstract void buildTopShelf(); - protected abstract void buildBottomShelf(); + protected abstract void addAchievements(); protected void add(String key, Achievement achievement) { achievements.put(key, achievement); @@ -103,7 +102,7 @@ public abstract class AchievementCollection implements Iterable { } } - private void save() { + protected void save() { try { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = builder.newDocument(); diff --git a/forge-gui/src/main/java/forge/achievement/AltWinAchievements.java b/forge-gui/src/main/java/forge/achievement/AltWinAchievements.java new file mode 100644 index 00000000000..cba61443c84 --- /dev/null +++ b/forge-gui/src/main/java/forge/achievement/AltWinAchievements.java @@ -0,0 +1,81 @@ +package forge.achievement; + +import org.apache.commons.lang3.StringUtils; + +import forge.assets.FSkinProp; +import forge.game.Game; +import forge.game.player.Player; +import forge.interfaces.IGuiBase; +import forge.properties.ForgeConstants; + +public class AltWinAchievements extends AchievementCollection { + public static final AltWinAchievements instance = new AltWinAchievements(); + + private AltWinAchievements() { + super("Alternate Win Conditions", ForgeConstants.ACHIEVEMENTS_DIR + "altwin.xml", false); + } + + @Override + protected void addSharedAchivements() { + //prevent including shared achievements + } + + @Override + protected void addAchievements() { + add("Azor's Elocutors", "The Filibuster", "Talk might be cheap, but it can buy you victory!", FSkinProp.IMG_THE_FILIBUSTER); + add("Barren Glory", "The Clean Slate", "When you have nothing, you can lose nothing... so you can win everything!", FSkinProp.IMG_THE_CLEAN_SLATE); + add("Battle of Wits", "The Library of Congress", "So many answers, so little time to look through them...", FSkinProp.IMG_THE_LIBRARY_OF_CONGRESS); + add("Biovisionary", "The Clique", "And now my... I mean our plan is complete!", FSkinProp.IMG_THE_CLIQUE); + add("Chance Encounter", "The Accident", "This victory was brought to you by a series of fortunate events.", FSkinProp.IMG_THE_ACCIDENT); + add("Coalition Victory", "The Teamwork", "Let's all be friends!", FSkinProp.IMG_THE_TEAMWORK); + add("Darksteel Reactor", "The Machine", "What are you going to do with all this power? Whatever you want!", FSkinProp.IMG_THE_MACHINE); + add("Epic Struggle", "The Army", "Let's just trample them into the ground already!", FSkinProp.IMG_THE_ARMY); + add("Felidar Sovereign", "The Cat's Life", "Just wait for his other eight lives!", FSkinProp.IMG_THE_CATS_LIFE); + add("Helix Pinnacle", "The Tower", "The view from the top is great!", FSkinProp.IMG_THE_TOWER); + add("Hellkite Tyrant", "The Hoard", "You made your bed of treasure, now lie in it!", FSkinProp.IMG_THE_HOARD); + add("Laboratory Maniac", "The Insanity", "No more questions? I'm omniscient now!", FSkinProp.IMG_THE_INSANITY); + add("Mayael's Aria", "The Gargantuan", "Just my shadow weighs a ton!", FSkinProp.IMG_THE_GARGANTUAN); + add("Maze's End", "The Labyrinth", "What? No bossfight?", FSkinProp.IMG_THE_LABYRINTH); + add("Mortal Combat", "The Boneyard", "So peaceful...", FSkinProp.IMG_THE_BONEYARD); + add("Near-Death Experience", "The Edge", "Phew... I thought I was going to die!", FSkinProp.IMG_THE_EDGE); + } + + private void add(String cardName0, String displayName0, String flavorText0, FSkinProp overlayImage0) { + add(getKey(cardName0), new AltWinAchievement(displayName0, cardName0, flavorText0, overlayImage0)); + } + + private String getKey(String cardName0) { + return cardName0.replaceAll(" ", ""); + } + + @Override + public void updateAll(IGuiBase gui, Player player) { + //only call update on achievement for alternate win condition (if any) + if (player.getOutcome().hasWon()) { + String altWinCondition = player.getOutcome().altWinSourceName; + if (!StringUtils.isEmpty(altWinCondition)) { + Achievement achievement = achievements.get(getKey(altWinCondition)); + if (achievement != null) { + achievement.update(gui, player); + save(); + } + } + } + } + + private class AltWinAchievement extends Achievement { + private AltWinAchievement(String displayName0, String cardName0, String flavorText0, FSkinProp overlayImage0) { + super(displayName0, "Win a game with " + cardName0, flavorText0, overlayImage0); + } + + @Override + protected int evaluate(Player player, Game game) { + return current + 1; //if this reaches this point, it can be presumed that alternate win condition achieved + } + + @Override + public String getSubTitle() { + return current + " Win" + (current != 1 ? "s" : ""); + } + } +} diff --git a/forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java b/forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java index 2b69498fe4d..deb5a1bd786 100644 --- a/forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java +++ b/forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java @@ -9,14 +9,9 @@ public class ConstructedAchievements extends AchievementCollection { super("Constructed", ForgeConstants.ACHIEVEMENTS_DIR + "constructed.xml", false); } - //add achievements that should appear at the top above core achievements for each game mode - @Override - protected void buildTopShelf() { - } - //add achievements that should appear at the bottom below core achievements for each game mode @Override - protected void buildBottomShelf() { + protected void addAchievements() { add("Vanguard", new VariantWins(GameType.Vanguard, 25, 50, 100, FSkinProp.IMG_VANGUARD)); add("MomirBasic", new VariantWins(GameType.MomirBasic, 25, 50, 100, FSkinProp.IMG_MOMIR_BASIC)); add("Commander", new VariantWins(GameType.Commander, 25, 50, 100, FSkinProp.IMG_COMMANDER)); diff --git a/forge-gui/src/main/java/forge/achievement/DeckedOut.java b/forge-gui/src/main/java/forge/achievement/DeckedOut.java index 968e0eff4c5..415e8b021e0 100644 --- a/forge-gui/src/main/java/forge/achievement/DeckedOut.java +++ b/forge-gui/src/main/java/forge/achievement/DeckedOut.java @@ -24,7 +24,7 @@ public class DeckedOut extends Achievement { @Override protected int evaluate(Player player, Game game) { if (player.getOutcome().hasWon()) { - Player opponent = getSingleOpponent(player); + Player opponent = player.getSingleOpponent(); if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) { return player.getTurn(); } diff --git a/forge-gui/src/main/java/forge/achievement/DraftAchievements.java b/forge-gui/src/main/java/forge/achievement/DraftAchievements.java index 1ff8ef7b51c..64641371941 100644 --- a/forge-gui/src/main/java/forge/achievement/DraftAchievements.java +++ b/forge-gui/src/main/java/forge/achievement/DraftAchievements.java @@ -7,13 +7,8 @@ public class DraftAchievements extends AchievementCollection { super("Booster Draft", ForgeConstants.ACHIEVEMENTS_DIR + "draft.xml", true); } - //add achievements that should appear at the top above core achievements for each game mode - @Override - protected void buildTopShelf() { - } - //add achievements that should appear at the bottom below core achievements for each game mode @Override - protected void buildBottomShelf() { + protected void addAchievements() { } } diff --git a/forge-gui/src/main/java/forge/achievement/Overkill.java b/forge-gui/src/main/java/forge/achievement/Overkill.java index 7dd7d802190..1b2c91d4021 100644 --- a/forge-gui/src/main/java/forge/achievement/Overkill.java +++ b/forge-gui/src/main/java/forge/achievement/Overkill.java @@ -19,7 +19,7 @@ public class Overkill extends Achievement { @Override protected int evaluate(Player player, Game game) { if (player.getOutcome().hasWon()) { - Player opponent = getSingleOpponent(player); + Player opponent = player.getSingleOpponent(); if (opponent != null && opponent.getLife() < 0) { return opponent.getLife(); } diff --git a/forge-gui/src/main/java/forge/achievement/Poisoned.java b/forge-gui/src/main/java/forge/achievement/Poisoned.java index c6d99a537e0..6b83b22f81d 100644 --- a/forge-gui/src/main/java/forge/achievement/Poisoned.java +++ b/forge-gui/src/main/java/forge/achievement/Poisoned.java @@ -20,7 +20,7 @@ public class Poisoned extends Achievement { @Override protected int evaluate(Player player, Game game) { if (player.getOutcome().hasWon()) { - Player opponent = getSingleOpponent(player); + Player opponent = player.getSingleOpponent(); if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) { return opponent.getPoisonCounters(); } diff --git a/forge-gui/src/main/java/forge/achievement/QuestAchievements.java b/forge-gui/src/main/java/forge/achievement/QuestAchievements.java index 47671bd4719..3181f95c5e8 100644 --- a/forge-gui/src/main/java/forge/achievement/QuestAchievements.java +++ b/forge-gui/src/main/java/forge/achievement/QuestAchievements.java @@ -7,14 +7,9 @@ public class QuestAchievements extends AchievementCollection { super("Quest Mode", ForgeConstants.ACHIEVEMENTS_DIR + "quest.xml", false); } - //add achievements that should appear at the top above core achievements for each game mode - @Override - protected void buildTopShelf() { - } - //add achievements that should appear at the bottom below core achievements for each game mode @Override - protected void buildBottomShelf() { + protected void addAchievements() { add("Poisoned", new Poisoned(15, 25, 40)); add("DeckedOut", new DeckedOut(8, 4, 2)); } diff --git a/forge-gui/src/main/java/forge/achievement/SealedAchievements.java b/forge-gui/src/main/java/forge/achievement/SealedAchievements.java index d5feb8a6eb2..08076022d20 100644 --- a/forge-gui/src/main/java/forge/achievement/SealedAchievements.java +++ b/forge-gui/src/main/java/forge/achievement/SealedAchievements.java @@ -7,13 +7,8 @@ public class SealedAchievements extends AchievementCollection { super("Sealed Deck", ForgeConstants.ACHIEVEMENTS_DIR + "sealed.xml", true); } - //add achievements that should appear at the top above core achievements for each game mode - @Override - protected void buildTopShelf() { - } - //add achievements that should appear at the bottom below core achievements for each game mode @Override - protected void buildBottomShelf() { + protected void addAchievements() { } } diff --git a/forge-gui/src/main/java/forge/player/GamePlayerUtil.java b/forge-gui/src/main/java/forge/player/GamePlayerUtil.java index 6991169ec1e..069d932839d 100644 --- a/forge-gui/src/main/java/forge/player/GamePlayerUtil.java +++ b/forge-gui/src/main/java/forge/player/GamePlayerUtil.java @@ -4,6 +4,7 @@ import forge.GuiBase; import forge.LobbyPlayer; import forge.ai.AiProfileUtil; import forge.ai.LobbyPlayerAi; +import forge.game.player.Player; import forge.interfaces.IGuiBase; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; @@ -59,6 +60,17 @@ public final class GamePlayerUtil { return player; } + public Player getSingleOpponent(Player player) { + if (player.getGame().getRegisteredPlayers().size() == 2) { + for (Player p : player.getGame().getRegisteredPlayers()) { + if (p.isOpponentOf(player)) { + return p; + } + } + } + return null; + } + public static void setPlayerName(final IGuiBase gui) { String oldPlayerName = FModel.getPreferences().getPref(FPref.PLAYER_NAME); String newPlayerName = null; diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 970e587a573..7017f27358a 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -32,6 +32,7 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import forge.LobbyPlayer; +import forge.achievement.AltWinAchievements; import forge.card.CardCharacteristicName; import forge.card.ColorSet; import forge.card.MagicColor; @@ -1344,13 +1345,14 @@ public class PlayerControllerHuman extends PlayerController { } public void updateAchievements() { - if (hasCheated()) { return; } //don't update achievements if player cheated during game + //if (hasCheated()) { return; } //don't update achievements if player cheated during game //update all achievements for GUI player after game finished ThreadUtil.invokeInGameThread(new Runnable() { @Override public void run() { FModel.getAchievements(game.getRules().getGameType()).updateAll(gui, player); + AltWinAchievements.instance.updateAll(gui, player); } }); }