mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Commit first set of alternate win achievements
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -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
|
||||
|
||||
@@ -322,6 +322,19 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -398,12 +398,12 @@ public enum VSubmenuAchievements implements IVSubmenu<CSubmenuAchievements> {
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -306,13 +306,13 @@ public class AchievementsPage extends TabPage<SettingsScreen> {
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -24,9 +24,9 @@ import forge.util.FileUtil;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class AchievementCollection implements Iterable<Achievement> {
|
||||
private final Map<String, Achievement> achievements = new LinkedHashMap<String, Achievement>();
|
||||
private final String name, filename;
|
||||
private final boolean isLimitedFormat;
|
||||
protected final Map<String, Achievement> achievements = new LinkedHashMap<String, Achievement>();
|
||||
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<Achievement> {
|
||||
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<Achievement> {
|
||||
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<Achievement> {
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
protected void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
|
||||
@@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user