Commit first set of alternate win achievements

This commit is contained in:
drdev
2014-09-21 15:22:59 +00:00
parent d6fa02582b
commit b5aa3b429e
16 changed files with 138 additions and 58 deletions

1
.gitattributes vendored
View File

@@ -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/UiCommand.java svneol=native#text/plain
forge-gui/src/main/java/forge/achievement/Achievement.java -text 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/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/Blackjack.java -text
forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java -text forge-gui/src/main/java/forge/achievement/ConstructedAchievements.java -text
forge-gui/src/main/java/forge/achievement/DeckedOut.java -text forge-gui/src/main/java/forge/achievement/DeckedOut.java -text

View File

@@ -322,6 +322,19 @@ public class Player extends GameEntity implements Comparable<Player> {
return result; 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. * Find the smallest life total amongst this player's opponents.
* *

View File

@@ -398,12 +398,12 @@ public enum VSubmenuAchievements implements IVSubmenu<CSubmenuAchievements> {
} }
y += PADDING; y += PADDING;
if (sharedDesc != null) { if (sharedDesc != null) {
g2d.drawString(sharedDesc + "...", x, y); g2d.drawString(selectedAchievement.isSpecial() ? sharedDesc : sharedDesc + "...", x, y);
y += descHeight; y += descHeight;
} }
if (mythicDesc != null) { if (mythicDesc != null) {
FSkin.setGraphicsColor(g2d, selectedAchievement.earnedMythic() ? TEXT_COLOR : NOT_EARNED_COLOR); 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; y += descHeight;
} }
if (rareDesc != null) { if (rareDesc != null) {

View File

@@ -306,13 +306,13 @@ public class AchievementsPage extends TabPage<SettingsScreen> {
} }
y += PADDING; y += PADDING;
if (sharedDesc != null) { 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); x, y, w, h, false, HAlignment.LEFT, false);
y += DESC_FONT.getLineHeight(); y += DESC_FONT.getLineHeight();
} }
if (mythicDesc != null) { if (mythicDesc != null) {
g.drawText("(Mythic) " + mythicDesc, DESC_FONT, g.drawText(selectedAchievement.isSpecial() ? mythicDesc : "(Mythic) " + mythicDesc, DESC_FONT, //handle flavor text here too
selectedAchievement.earnedRare() ? TEXT_COLOR : NOT_EARNED_COLOR, selectedAchievement.earnedMythic() ? TEXT_COLOR : NOT_EARNED_COLOR,
x, y, w, h, false, HAlignment.LEFT, false); x, y, w, h, false, HAlignment.LEFT, false);
y += DESC_FONT.getLineHeight(); y += DESC_FONT.getLineHeight();
} }

View File

@@ -18,8 +18,8 @@ public abstract class Achievement {
protected int best, current; protected int best, current;
//use this constructor for special achievements without tiers //use this constructor for special achievements without tiers
protected Achievement(String displayName0, String description0, FSkinProp overlayImage0) { protected Achievement(String displayName0, String description0, String flavorText0, FSkinProp overlayImage0) {
this(displayName0, description0, null, 1, null, 1, null, 1, null, 1, 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 //use this constructor for regular tiered achievements
protected Achievement(String displayName0, String sharedDesc0, protected Achievement(String displayName0, String sharedDesc0,
@@ -39,7 +39,7 @@ public abstract class Achievement {
mythicDesc = mythicDesc0; mythicDesc = mythicDesc0;
mythicThreshold = mythicThreshold0; mythicThreshold = mythicThreshold0;
overlayImage = overlayImage0; overlayImage = overlayImage0;
checkGreaterThan = rareThreshold0 > uncommonThreshold0; checkGreaterThan = rareThreshold0 >= uncommonThreshold0;
} }
public String getDisplayName() { public String getDisplayName() {
@@ -66,8 +66,11 @@ public abstract class Achievement {
} }
return image; return image;
} }
public boolean isSpecial() {
return mythicThreshold == commonThreshold;
}
private boolean earnedSpecial() { private boolean earnedSpecial() {
return (mythicThreshold == commonThreshold && best > 1); return (isSpecial() && best > 0);
} }
public boolean earnedMythic() { public boolean earnedMythic() {
if (checkGreaterThan) { if (checkGreaterThan) {
@@ -96,17 +99,6 @@ public abstract class Achievement {
protected abstract int evaluate(Player player, Game game); 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() { private void updateTrophyImage() {
FSkinProp background; FSkinProp background;
float opacity = 1; float opacity = 1;

View File

@@ -24,9 +24,9 @@ import forge.util.FileUtil;
import forge.util.XmlUtil; import forge.util.XmlUtil;
public abstract class AchievementCollection implements Iterable<Achievement> { public abstract class AchievementCollection implements Iterable<Achievement> {
private final Map<String, Achievement> achievements = new LinkedHashMap<String, Achievement>(); protected final Map<String, Achievement> achievements = new LinkedHashMap<String, Achievement>();
private final String name, filename; protected final String name, filename;
private final boolean isLimitedFormat; protected final boolean isLimitedFormat;
static { static {
FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR); FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR);
@@ -37,19 +37,19 @@ public abstract class AchievementCollection implements Iterable<Achievement> {
cb.addItem(FModel.getAchievements(GameType.Draft)); cb.addItem(FModel.getAchievements(GameType.Draft));
cb.addItem(FModel.getAchievements(GameType.Sealed)); cb.addItem(FModel.getAchievements(GameType.Sealed));
cb.addItem(FModel.getAchievements(GameType.Quest)); cb.addItem(FModel.getAchievements(GameType.Quest));
cb.addItem(AltWinAchievements.instance);
} }
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) { protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) {
name = name0; name = name0;
filename = filename0; filename = filename0;
isLimitedFormat = isLimitedFormat0; isLimitedFormat = isLimitedFormat0;
buildTopShelf(); addSharedAchivements();
buildCoreShelves(); addAchievements();
buildBottomShelf();
load(); load();
} }
private void buildCoreShelves() { protected void addSharedAchivements() {
add("GameWinStreak", new GameWinStreak(10, 25, 50, 100)); add("GameWinStreak", new GameWinStreak(10, 25, 50, 100));
add("MatchWinStreak", new MatchWinStreak(10, 25, 50, 100)); add("MatchWinStreak", new MatchWinStreak(10, 25, 50, 100));
add("TotalGameWins", new TotalGameWins(250, 500, 1000, 2000)); add("TotalGameWins", new TotalGameWins(250, 500, 1000, 2000));
@@ -65,8 +65,7 @@ public abstract class AchievementCollection implements Iterable<Achievement> {
add("Hellbent", new Hellbent()); add("Hellbent", new Hellbent());
} }
protected abstract void buildTopShelf(); protected abstract void addAchievements();
protected abstract void buildBottomShelf();
protected void add(String key, Achievement achievement) { protected void add(String key, Achievement achievement) {
achievements.put(key, achievement); achievements.put(key, achievement);
@@ -103,7 +102,7 @@ public abstract class AchievementCollection implements Iterable<Achievement> {
} }
} }
private void save() { protected void save() {
try { try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.newDocument(); Document document = builder.newDocument();

View File

@@ -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" : "");
}
}
}

View File

@@ -9,14 +9,9 @@ public class ConstructedAchievements extends AchievementCollection {
super("Constructed", ForgeConstants.ACHIEVEMENTS_DIR + "constructed.xml", false); 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 //add achievements that should appear at the bottom below core achievements for each game mode
@Override @Override
protected void buildBottomShelf() { protected void addAchievements() {
add("Vanguard", new VariantWins(GameType.Vanguard, 25, 50, 100, FSkinProp.IMG_VANGUARD)); 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("MomirBasic", new VariantWins(GameType.MomirBasic, 25, 50, 100, FSkinProp.IMG_MOMIR_BASIC));
add("Commander", new VariantWins(GameType.Commander, 25, 50, 100, FSkinProp.IMG_COMMANDER)); add("Commander", new VariantWins(GameType.Commander, 25, 50, 100, FSkinProp.IMG_COMMANDER));

View File

@@ -24,7 +24,7 @@ public class DeckedOut extends Achievement {
@Override @Override
protected int evaluate(Player player, Game game) { protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) { if (player.getOutcome().hasWon()) {
Player opponent = getSingleOpponent(player); Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) { if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) {
return player.getTurn(); return player.getTurn();
} }

View File

@@ -7,13 +7,8 @@ public class DraftAchievements extends AchievementCollection {
super("Booster Draft", ForgeConstants.ACHIEVEMENTS_DIR + "draft.xml", true); 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 //add achievements that should appear at the bottom below core achievements for each game mode
@Override @Override
protected void buildBottomShelf() { protected void addAchievements() {
} }
} }

View File

@@ -19,7 +19,7 @@ public class Overkill extends Achievement {
@Override @Override
protected int evaluate(Player player, Game game) { protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) { if (player.getOutcome().hasWon()) {
Player opponent = getSingleOpponent(player); Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getLife() < 0) { if (opponent != null && opponent.getLife() < 0) {
return opponent.getLife(); return opponent.getLife();
} }

View File

@@ -20,7 +20,7 @@ public class Poisoned extends Achievement {
@Override @Override
protected int evaluate(Player player, Game game) { protected int evaluate(Player player, Game game) {
if (player.getOutcome().hasWon()) { if (player.getOutcome().hasWon()) {
Player opponent = getSingleOpponent(player); Player opponent = player.getSingleOpponent();
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) { if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) {
return opponent.getPoisonCounters(); return opponent.getPoisonCounters();
} }

View File

@@ -7,14 +7,9 @@ public class QuestAchievements extends AchievementCollection {
super("Quest Mode", ForgeConstants.ACHIEVEMENTS_DIR + "quest.xml", false); 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 //add achievements that should appear at the bottom below core achievements for each game mode
@Override @Override
protected void buildBottomShelf() { protected void addAchievements() {
add("Poisoned", new Poisoned(15, 25, 40)); add("Poisoned", new Poisoned(15, 25, 40));
add("DeckedOut", new DeckedOut(8, 4, 2)); add("DeckedOut", new DeckedOut(8, 4, 2));
} }

View File

@@ -7,13 +7,8 @@ public class SealedAchievements extends AchievementCollection {
super("Sealed Deck", ForgeConstants.ACHIEVEMENTS_DIR + "sealed.xml", true); 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 //add achievements that should appear at the bottom below core achievements for each game mode
@Override @Override
protected void buildBottomShelf() { protected void addAchievements() {
} }
} }

View File

@@ -4,6 +4,7 @@ import forge.GuiBase;
import forge.LobbyPlayer; import forge.LobbyPlayer;
import forge.ai.AiProfileUtil; import forge.ai.AiProfileUtil;
import forge.ai.LobbyPlayerAi; import forge.ai.LobbyPlayerAi;
import forge.game.player.Player;
import forge.interfaces.IGuiBase; import forge.interfaces.IGuiBase;
import forge.model.FModel; import forge.model.FModel;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
@@ -59,6 +60,17 @@ public final class GamePlayerUtil {
return player; 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) { public static void setPlayerName(final IGuiBase gui) {
String oldPlayerName = FModel.getPreferences().getPref(FPref.PLAYER_NAME); String oldPlayerName = FModel.getPreferences().getPref(FPref.PLAYER_NAME);
String newPlayerName = null; String newPlayerName = null;

View File

@@ -32,6 +32,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import forge.LobbyPlayer; import forge.LobbyPlayer;
import forge.achievement.AltWinAchievements;
import forge.card.CardCharacteristicName; import forge.card.CardCharacteristicName;
import forge.card.ColorSet; import forge.card.ColorSet;
import forge.card.MagicColor; import forge.card.MagicColor;
@@ -1344,13 +1345,14 @@ public class PlayerControllerHuman extends PlayerController {
} }
public void updateAchievements() { 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 //update all achievements for GUI player after game finished
ThreadUtil.invokeInGameThread(new Runnable() { ThreadUtil.invokeInGameThread(new Runnable() {
@Override @Override
public void run() { public void run() {
FModel.getAchievements(game.getRules().getGameType()).updateAll(gui, player); FModel.getAchievements(game.getRules().getGameType()).updateAll(gui, player);
AltWinAchievements.instance.updateAll(gui, player);
} }
}); });
} }