mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Draft Matters - How many cards you've drafted this round (#5203)
This commit is contained in:
@@ -51,6 +51,7 @@ final class CardFace implements ICardFace, Cloneable {
|
||||
private List<String> abilities = null;
|
||||
private List<String> staticAbilities = null;
|
||||
private List<String> triggers = null;
|
||||
private List<String> draftActions = null;
|
||||
private List<String> replacements = null;
|
||||
private Map<String, String> variables = null;
|
||||
|
||||
@@ -74,6 +75,7 @@ final class CardFace implements ICardFace, Cloneable {
|
||||
@Override public Iterable<String> getAbilities() { return abilities; }
|
||||
@Override public Iterable<String> getStaticAbilities() { return staticAbilities; }
|
||||
@Override public Iterable<String> getTriggers() { return triggers; }
|
||||
@Override public Iterable<String> getDraftActions() { return draftActions; }
|
||||
@Override public Iterable<String> getReplacements() { return replacements; }
|
||||
@Override public String getNonAbilityText() { return nonAbilityText; }
|
||||
@Override public Iterable<Entry<String, String>> getVariables() { return variables.entrySet(); }
|
||||
@@ -125,6 +127,7 @@ final class CardFace implements ICardFace, Cloneable {
|
||||
void addKeyword(String value) { if (null == this.keywords) { this.keywords = new ArrayList<>(); } this.keywords.add(value); }
|
||||
void addAbility(String value) { if (null == this.abilities) { this.abilities = new ArrayList<>(); } this.abilities.add(value);}
|
||||
void addTrigger(String value) { if (null == this.triggers) { this.triggers = new ArrayList<>(); } this.triggers.add(value);}
|
||||
void addDraftAction(String value) { if (null == this.draftActions) { this.draftActions = new ArrayList<>(); } this.draftActions.add(value);}
|
||||
void addStaticAbility(String value) { if (null == this.staticAbilities) { this.staticAbilities = new ArrayList<>(); } this.staticAbilities.add(value);}
|
||||
void addReplacementEffect(String value) { if (null == this.replacements) { this.replacements = new ArrayList<>(); } this.replacements.add(value);}
|
||||
void addSVar(String key, String value) { if (null == this.variables) { this.variables = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); } this.variables.put(key, value); }
|
||||
|
||||
@@ -547,6 +547,8 @@ public final class CardRules implements ICardCharacteristics {
|
||||
has = new DeckHints(value);
|
||||
} else if ("Defense".equals(key)) {
|
||||
this.faces[this.curFace].setDefense(value);
|
||||
} else if ("Draft".equals(key)) {
|
||||
this.faces[this.curFace].addDraftAction(value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ public interface ICardRawAbilites
|
||||
Iterable<String> getKeywords();
|
||||
Iterable<String> getReplacements();
|
||||
Iterable<String> getTriggers();
|
||||
Iterable<String> getDraftActions();
|
||||
Iterable<String> getStaticAbilities();
|
||||
Iterable<String> getAbilities();
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
// Supports deferring loading a deck until we actually need its contents. This works in conjunction with
|
||||
// the lazy card load feature to ensure we don't need to load all cards on start up.
|
||||
private final Set<String> aiHints = new TreeSet<>();
|
||||
private final Map<String, String> draftNotes = new HashMap<>();
|
||||
private Map<String, List<String>> deferredSections = null;
|
||||
private Map<String, List<String>> loadedSections = null;
|
||||
private String lastCardArtPreferenceUsed = "";
|
||||
@@ -91,10 +92,6 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
public Deck(final Deck other, final String newName) {
|
||||
super(newName);
|
||||
other.cloneFieldsTo(this);
|
||||
for (final Entry<DeckSection, CardPool> sections : other.parts.entrySet()) {
|
||||
parts.put(sections.getKey(), new CardPool(sections.getValue()));
|
||||
}
|
||||
tags.addAll(other.getTags());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -209,6 +206,8 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
cp.addAll(kv.getValue());
|
||||
}
|
||||
result.setAiHints(StringUtils.join(aiHints, " | "));
|
||||
result.setDraftNotes(draftNotes);
|
||||
tags.addAll(result.getTags());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -561,6 +560,24 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setDraftNotes(Map<String, String> draftNotes) {
|
||||
if (draftNotes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(String key : draftNotes.keySet()) {
|
||||
String notes = draftNotes.get(key);
|
||||
if (notes == null || notes.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
this.draftNotes.put(key, notes.trim());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getDraftNotes() {
|
||||
return draftNotes;
|
||||
}
|
||||
|
||||
public UnplayableAICards getUnplayableAICards() {
|
||||
if (unplayableAI == null) {
|
||||
unplayableAI = new UnplayableAICards(this);
|
||||
|
||||
@@ -26,7 +26,8 @@ import java.util.List;
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
* Related decks usually pertaining to a limited experience like draft or sealed
|
||||
* This file represents a human player deck and all opposing AI decks
|
||||
*
|
||||
*/
|
||||
public class DeckGroup extends DeckBase {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package forge.deck.io;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@@ -39,6 +40,7 @@ public class DeckFileHeader {
|
||||
public static final String TAGS = "Tags";
|
||||
|
||||
public static final String TAGS_SEPARATOR = ",";
|
||||
public static final String DRAFT_NOTES = "DraftNotes";
|
||||
|
||||
/** The Constant COMMENT. */
|
||||
public static final String COMMENT = "Comment";
|
||||
@@ -54,30 +56,19 @@ public class DeckFileHeader {
|
||||
private final String comment;
|
||||
|
||||
private final Set<String> tags;
|
||||
private final HashMap<String, String> draftNotes;
|
||||
|
||||
private final boolean intendedForAi;
|
||||
private final String aiHints;
|
||||
|
||||
/**
|
||||
* @return the intendedForAi
|
||||
*/
|
||||
public boolean isIntendedForAi() {
|
||||
return intendedForAi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the AI hints
|
||||
*/
|
||||
public String getAiHints() {
|
||||
return aiHints;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
*
|
||||
* @param kvPairs
|
||||
* the kv pairs
|
||||
*/
|
||||
public DeckFileHeader(final FileSection kvPairs) {
|
||||
this.name = kvPairs.get(DeckFileHeader.NAME);
|
||||
this.comment = kvPairs.get(DeckFileHeader.COMMENT);
|
||||
@@ -85,6 +76,7 @@ public class DeckFileHeader {
|
||||
this.customPool = kvPairs.getBoolean(DeckFileHeader.CSTM_POOL);
|
||||
this.intendedForAi = "computer".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER)) || "ai".equalsIgnoreCase(kvPairs.get(DeckFileHeader.PLAYER_TYPE));
|
||||
this.aiHints = kvPairs.get(DeckFileHeader.AI_HINTS);
|
||||
|
||||
this.tags = new TreeSet<>();
|
||||
|
||||
String rawTags = kvPairs.get(DeckFileHeader.TAGS);
|
||||
@@ -93,42 +85,42 @@ public class DeckFileHeader {
|
||||
if ( StringUtils.isNotBlank(t))
|
||||
tags.add(t.trim());
|
||||
}
|
||||
|
||||
|
||||
this.draftNotes = new HashMap<>();
|
||||
extractDraftNotes(kvPairs.get(DeckFileHeader.DRAFT_NOTES));
|
||||
}
|
||||
|
||||
private void extractDraftNotes(String rawNotes) {
|
||||
if(StringUtils.isBlank(rawNotes) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(String t : rawNotes.split("\\|")) {
|
||||
if (StringUtils.isBlank(t)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] notes = t.trim().split(":", 2);
|
||||
|
||||
if (notes[0].trim().isEmpty() || notes[1].trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
draftNotes.put(notes[0].trim(), notes[1].trim());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is custom pool.
|
||||
*
|
||||
* @return true, if is custom pool
|
||||
*/
|
||||
public final boolean isCustomPool() {
|
||||
return this.customPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the comment.
|
||||
*
|
||||
* @return the comment
|
||||
*/
|
||||
public final String getComment() {
|
||||
return this.comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the deck type.
|
||||
*
|
||||
* @return the deck type
|
||||
*/
|
||||
public final DeckFormat getDeckType() {
|
||||
return this.deckType;
|
||||
}
|
||||
@@ -137,4 +129,7 @@ public class DeckFileHeader {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public final HashMap<String, String> getDraftNotes() {
|
||||
return draftNotes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,30 @@ public class DeckSerializer {
|
||||
if (!d.getAiHints().isEmpty()) {
|
||||
out.add(TextUtil.concatNoSpace(DeckFileHeader.AI_HINTS, "=", StringUtils.join(d.getAiHints(), " | ")));
|
||||
}
|
||||
if (!d.getDraftNotes().isEmpty()) {
|
||||
String sb = serializeDraftNotes(d.getDraftNotes());
|
||||
out.add(TextUtil.concatNoSpace(DeckFileHeader.DRAFT_NOTES, "=", sb));
|
||||
}
|
||||
|
||||
for(Entry<DeckSection, CardPool> s : d) {
|
||||
out.add(TextUtil.enclosedBracket(s.getKey().toString()));
|
||||
out.add(s.getValue().toCardList(System.getProperty("line.separator")));
|
||||
out.add(s.getValue().toCardList(System.lineSeparator()));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String serializeDraftNotes(final Map<String, String> draftNotes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(String key : draftNotes.keySet()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" | ");
|
||||
}
|
||||
|
||||
sb.append(key).append(":").append(draftNotes.get(key));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static Deck fromFile(final File deckFile) {
|
||||
return fromSections(FileSection.parseSections(FileUtil.readFile(deckFile)));
|
||||
}
|
||||
@@ -82,6 +98,7 @@ public class DeckSerializer {
|
||||
d.setComment(dh.getComment());
|
||||
d.setAiHints(dh.getAiHints());
|
||||
d.getTags().addAll(dh.getTags());
|
||||
d.setDraftNotes(dh.getDraftNotes());
|
||||
d.setDeferredSections(sections);
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -288,6 +288,7 @@ public class Match {
|
||||
}
|
||||
|
||||
Deck myDeck = psc.getDeck();
|
||||
player.setDraftNotes(myDeck.getDraftNotes());
|
||||
|
||||
Set<PaperCard> myRemovedAnteCards = null;
|
||||
if (!rules.useAnte()) {
|
||||
|
||||
@@ -2358,6 +2358,23 @@ public class AbilityUtils {
|
||||
return doXMath(player.getNotedNumberForName(c.getName()), expr, c, ctb);
|
||||
}
|
||||
|
||||
if (sq[0].equals("DraftNotesHighest")) {
|
||||
// Just in case you are playing this card in a deck without draft notes
|
||||
String note = player.getDraftNotes().getOrDefault(sq[1], "0");
|
||||
int highest = 0;
|
||||
for (String n : note.split(",")) {
|
||||
int num = Integer.parseInt(n);
|
||||
if (num > highest) {
|
||||
highest = num;
|
||||
}
|
||||
}
|
||||
|
||||
return doXMath(highest, expr, c, ctb);
|
||||
// Other draft notes include: Names, Colors, Players, Creature Type.
|
||||
// But these aren't really things you count so they'll show up in properties most likely
|
||||
}
|
||||
|
||||
|
||||
//Count$TypesSharedWith [defined]
|
||||
if (sq[0].startsWith("TypesSharedWith")) {
|
||||
Set<CardType.CoreType> thisTypes = Sets.newHashSet(c.getType().getCoreTypes());
|
||||
|
||||
@@ -124,6 +124,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
|
||||
private final Map<String, FCollection<String>> notes = Maps.newHashMap();
|
||||
private final Map<String, Integer> notedNum = Maps.newHashMap();
|
||||
private final Map<String, String> draftNotes = Maps.newHashMap();
|
||||
|
||||
private boolean revolt = false;
|
||||
private int descended = 0;
|
||||
@@ -2376,6 +2377,15 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
|
||||
public void setDraftNotes(Map<String, String> notes) {
|
||||
this.draftNotes.clear();
|
||||
this.draftNotes.putAll(notes);
|
||||
}
|
||||
|
||||
public Map<String, String> getDraftNotes() {
|
||||
return draftNotes;
|
||||
}
|
||||
|
||||
public static class Accessors {
|
||||
public static Function<Player, String> FN_GET_NAME = new Function<Player, String>() {
|
||||
@Override
|
||||
|
||||
@@ -5,16 +5,7 @@ package forge.gui.framework;
|
||||
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
|
||||
import forge.screens.deckeditor.views.VAllDecks;
|
||||
import forge.screens.deckeditor.views.VBrawlDecks;
|
||||
import forge.screens.deckeditor.views.VCardCatalog;
|
||||
import forge.screens.deckeditor.views.VCommanderDecks;
|
||||
import forge.screens.deckeditor.views.VCurrentDeck;
|
||||
import forge.screens.deckeditor.views.VDeckgen;
|
||||
import forge.screens.deckeditor.views.VOathbreakerDecks;
|
||||
import forge.screens.deckeditor.views.VProbabilities;
|
||||
import forge.screens.deckeditor.views.VStatistics;
|
||||
import forge.screens.deckeditor.views.VTinyLeadersDecks;
|
||||
import forge.screens.deckeditor.views.*;
|
||||
import forge.screens.home.gauntlet.*;
|
||||
import forge.screens.home.online.VSubmenuOnlineLobby;
|
||||
import forge.screens.home.puzzle.VSubmenuPuzzleCreate;
|
||||
@@ -61,6 +52,7 @@ public enum EDocID {
|
||||
EDITOR_BRAWL (VBrawlDecks.SINGLETON_INSTANCE),
|
||||
EDITOR_TINY_LEADERS (VTinyLeadersDecks.SINGLETON_INSTANCE),
|
||||
EDITOR_OATHBREAKER (VOathbreakerDecks.SINGLETON_INSTANCE),
|
||||
EDITOR_LOG(VEditorLog.SINGLETON_INSTANCE),
|
||||
|
||||
WORKSHOP_CATALOG (VWorkshopCatalog.SINGLETON_INSTANCE),
|
||||
WORKSHOP_CARDDESIGNER (VCardDesigner.SINGLETON_INSTANCE),
|
||||
|
||||
@@ -42,13 +42,7 @@ import forge.screens.deckeditor.controllers.CEditorQuestCardShop;
|
||||
import forge.screens.deckeditor.controllers.CProbabilities;
|
||||
import forge.screens.deckeditor.controllers.CStatistics;
|
||||
import forge.screens.deckeditor.controllers.DeckController;
|
||||
import forge.screens.deckeditor.views.VAllDecks;
|
||||
import forge.screens.deckeditor.views.VBrawlDecks;
|
||||
import forge.screens.deckeditor.views.VCardCatalog;
|
||||
import forge.screens.deckeditor.views.VCommanderDecks;
|
||||
import forge.screens.deckeditor.views.VCurrentDeck;
|
||||
import forge.screens.deckeditor.views.VOathbreakerDecks;
|
||||
import forge.screens.deckeditor.views.VTinyLeadersDecks;
|
||||
import forge.screens.deckeditor.views.*;
|
||||
import forge.screens.match.controllers.CDetailPicture;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
@@ -72,6 +66,7 @@ public enum CDeckEditorUI implements ICDoc {
|
||||
private final VOathbreakerDecks vOathbreakerDecks;
|
||||
private final VBrawlDecks vBrawlDecks;
|
||||
private final VTinyLeadersDecks vTinyLeadersDecks;
|
||||
private final VEditorLog vEditorLog;
|
||||
|
||||
CDeckEditorUI() {
|
||||
screenChildControllers = new HashMap<>();
|
||||
@@ -86,6 +81,7 @@ public enum CDeckEditorUI implements ICDoc {
|
||||
this.vBrawlDecks.setCDetailPicture(cDetailPicture);
|
||||
this.vTinyLeadersDecks = VTinyLeadersDecks.SINGLETON_INSTANCE;
|
||||
this.vTinyLeadersDecks.setCDetailPicture(cDetailPicture);
|
||||
this.vEditorLog = VEditorLog.SINGLETON_INSTANCE;
|
||||
}
|
||||
|
||||
public CDetailPicture getCDetailPicture() {
|
||||
@@ -232,7 +228,7 @@ public enum CDeckEditorUI implements ICDoc {
|
||||
if (e.isControlDown() || e.isMetaDown()) {
|
||||
deckView.focus();
|
||||
e.consume(); //prevent losing selection
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -308,6 +304,7 @@ public enum CDeckEditorUI implements ICDoc {
|
||||
public void register() {
|
||||
EDocID.CARD_PICTURE.setDoc(cDetailPicture.getCPicture().getView());
|
||||
EDocID.CARD_DETAIL.setDoc(cDetailPicture.getCDetail().getView());
|
||||
EDocID.EDITOR_LOG.setDoc(vEditorLog);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -27,6 +27,8 @@ import forge.deck.DeckSection;
|
||||
import forge.game.GameType;
|
||||
import forge.gamemodes.limited.BoosterDraft;
|
||||
import forge.gamemodes.limited.IBoosterDraft;
|
||||
import forge.gamemodes.limited.IDraftLog;
|
||||
import forge.gamemodes.limited.LimitedPlayer;
|
||||
import forge.gui.framework.DragCell;
|
||||
import forge.gui.framework.FScreen;
|
||||
import forge.item.PaperCard;
|
||||
@@ -34,13 +36,7 @@ import forge.itemmanager.CardManager;
|
||||
import forge.itemmanager.ItemManagerConfig;
|
||||
import forge.model.FModel;
|
||||
import forge.screens.deckeditor.CDeckEditorUI;
|
||||
import forge.screens.deckeditor.views.VAllDecks;
|
||||
import forge.screens.deckeditor.views.VBrawlDecks;
|
||||
import forge.screens.deckeditor.views.VCommanderDecks;
|
||||
import forge.screens.deckeditor.views.VCurrentDeck;
|
||||
import forge.screens.deckeditor.views.VDeckgen;
|
||||
import forge.screens.deckeditor.views.VOathbreakerDecks;
|
||||
import forge.screens.deckeditor.views.VTinyLeadersDecks;
|
||||
import forge.screens.deckeditor.views.*;
|
||||
import forge.screens.home.sanctioned.CSubmenuDraft;
|
||||
import forge.screens.match.controllers.CDetailPicture;
|
||||
import forge.toolbox.FOptionPane;
|
||||
@@ -55,7 +51,7 @@ import forge.util.Localizer;
|
||||
* @author Forge
|
||||
* @version $Id: CEditorDraftingProcess.java 24872 2014-02-17 07:35:47Z drdev $
|
||||
*/
|
||||
public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> implements IDraftLog {
|
||||
private IBoosterDraft boosterDraft;
|
||||
|
||||
private String ccAddLabel = Localizer.getInstance().getMessage("lblAddcard");
|
||||
@@ -65,6 +61,7 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
private DragCell brawlDecksParent = null;
|
||||
private DragCell tinyLeadersDecksParent = null;
|
||||
private DragCell deckGenParent = null;
|
||||
private DragCell draftLogParent = null;
|
||||
private boolean saved = false;
|
||||
private final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
@@ -99,6 +96,13 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
*/
|
||||
public final void showGui(final IBoosterDraft inBoosterDraft) {
|
||||
this.boosterDraft = inBoosterDraft;
|
||||
this.boosterDraft.setLogEntry(this);
|
||||
|
||||
this.addLogEntry("Drafting process started.");
|
||||
}
|
||||
|
||||
public void addLogEntry(String message) {
|
||||
CEditorLog.SINGLETON_INSTANCE.addLogEntry(message);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -110,6 +114,8 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
|
||||
// can only draft one at a time, regardless of the requested quantity
|
||||
PaperCard card = items.iterator().next().getKey();
|
||||
|
||||
// Verify if card is in the activate pack?
|
||||
this.getDeckManager().addItem(card, 1);
|
||||
|
||||
// get next booster pack
|
||||
@@ -212,16 +218,30 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
|
||||
} while(s == null || s.isEmpty());
|
||||
|
||||
saved = true;
|
||||
|
||||
// Construct computer's decks and save draft
|
||||
final Deck[] computer = this.boosterDraft.getDecks();
|
||||
final LimitedPlayer[] players = this.boosterDraft.getOpposingPlayers();
|
||||
|
||||
for(int i = 0; i < computer.length; i++) {
|
||||
Deck deck = computer[i];
|
||||
LimitedPlayer player = players[i];
|
||||
|
||||
deck.setDraftNotes(player.getSerializedDraftNotes());
|
||||
}
|
||||
|
||||
// Assigned noted stuff to deck from LimitedPlayer
|
||||
final DeckGroup finishedDraft = new DeckGroup(s);
|
||||
finishedDraft.setHumanDeck((Deck) this.getPlayersDeck().copyTo(s));
|
||||
final LimitedPlayer player = this.boosterDraft.getHumanPlayer();
|
||||
|
||||
Deck humanDeck = (Deck) this.getPlayersDeck().copyTo(s);
|
||||
humanDeck.setDraftNotes(player.getSerializedDraftNotes());
|
||||
finishedDraft.setHumanDeck(humanDeck);
|
||||
finishedDraft.addAiDecks(computer);
|
||||
|
||||
FModel.getDecks().getDraft().add(finishedDraft);
|
||||
|
||||
saved = true;
|
||||
|
||||
CSubmenuDraft.SINGLETON_INSTANCE.update();
|
||||
FScreen.DRAFTING_PROCESS.close();
|
||||
|
||||
@@ -267,6 +287,11 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
this.getCatalogManager().setup(ItemManagerConfig.DRAFT_PACK);
|
||||
this.getDeckManager().setup(ItemManagerConfig.DRAFT_POOL);
|
||||
|
||||
if (VEditorLog.SINGLETON_INSTANCE.getParentCell() == null) {
|
||||
VCardCatalog.SINGLETON_INSTANCE.getParentCell().addDoc(VEditorLog.SINGLETON_INSTANCE);
|
||||
VEditorLog.SINGLETON_INSTANCE.showView();
|
||||
}
|
||||
|
||||
ccAddLabel = this.getBtnAdd().getText();
|
||||
|
||||
if (this.getDeckManager().getPool() == null) { //avoid showing next choice or resetting pool if just switching back to Draft screen
|
||||
@@ -327,6 +352,7 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
this.getBtnRemove4().setVisible(true);
|
||||
|
||||
VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true);
|
||||
VEditorLog.SINGLETON_INSTANCE.getParentCell().setVisible(true);
|
||||
|
||||
//Re-add tabs
|
||||
if (deckGenParent != null) {
|
||||
@@ -347,6 +373,9 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
||||
if (tinyLeadersDecksParent != null) {
|
||||
tinyLeadersDecksParent.addDoc(VTinyLeadersDecks.SINGLETON_INSTANCE);
|
||||
}
|
||||
if (draftLogParent != null) {
|
||||
draftLogParent.addDoc(VEditorLog.SINGLETON_INSTANCE);
|
||||
}
|
||||
|
||||
// set catalog table back to free-selection mode
|
||||
getCatalogManager().setAllowMultipleSelections(true);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package forge.screens.deckeditor.controllers;
|
||||
|
||||
import forge.gui.FThreads;
|
||||
import forge.gui.framework.ICDoc;
|
||||
import forge.screens.deckeditor.views.VEditorLog;
|
||||
|
||||
/**
|
||||
* Controls the "editor log" panel in the deck editor UI.
|
||||
*
|
||||
* <br><br><i>(C at beginning of class name denotes a control class.)</i>
|
||||
*
|
||||
*/
|
||||
public enum CEditorLog implements ICDoc {
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
/** */
|
||||
CEditorDraftingProcess draftingProcess;
|
||||
|
||||
private final VEditorLog view;
|
||||
|
||||
CEditorLog() {
|
||||
this.view = VEditorLog.SINGLETON_INSTANCE;
|
||||
}
|
||||
|
||||
//========== Overridden methods
|
||||
|
||||
public final VEditorLog getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
public final void addLogEntry(final String entry) {
|
||||
view.addLogEntry(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.ICDoc#initialize()
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
FThreads.invokeInEdtNowOrLater(reset);
|
||||
}
|
||||
|
||||
private final Runnable reset = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
view.resetNewDraft();
|
||||
}
|
||||
};
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.framework.ICDoc#update()
|
||||
*/
|
||||
@Override
|
||||
public void update() {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
view.updateConsole();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package forge.screens.deckeditor.views;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.gui.framework.DragCell;
|
||||
import forge.gui.framework.DragTab;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.IVDoc;
|
||||
import forge.screens.deckeditor.controllers.CEditorLog;
|
||||
import forge.screens.match.GameLogPanel;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.util.Localizer;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Assembles Swing components of card catalog in deck editor.
|
||||
*
|
||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||
*
|
||||
*/
|
||||
public enum VEditorLog implements IVDoc<CEditorLog> {
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
private final DragTab tab = new DragTab(localizer.getMessage("lblEditorLog"));
|
||||
|
||||
private final GameLogPanel gameLog;
|
||||
|
||||
private final JPanel pnlContent = new JPanel(new MigLayout("insets 0, gap 0, wrap"));
|
||||
private final FScrollPane scroller = new FScrollPane(pnlContent, false);
|
||||
|
||||
|
||||
private final List<String> editorLogEntries = Lists.newArrayList();
|
||||
|
||||
VEditorLog() {
|
||||
pnlContent.setOpaque(false);
|
||||
scroller.getViewport().setBorder(null);
|
||||
|
||||
this.gameLog = new GameLogPanel();
|
||||
}
|
||||
|
||||
//========== Overridden from IVDoc
|
||||
|
||||
@Override
|
||||
public EDocID getDocumentID() {
|
||||
return EDocID.EDITOR_LOG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragTab getTabLabel() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
public void showView() {
|
||||
tab.setVisible(true);
|
||||
tab.setOpaque(true);
|
||||
pnlContent.setOpaque(true);
|
||||
pnlContent.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CEditorLog getLayoutControl() {
|
||||
return CEditorLog.SINGLETON_INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentCell(final DragCell cell0) {
|
||||
this.parentCell = cell0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragCell getParentCell() {
|
||||
return this.parentCell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate() {
|
||||
final JPanel parentBody = parentCell.getBody();
|
||||
parentBody.setLayout(new MigLayout("insets 5, gap 0, wrap, hidemode 3"));
|
||||
// Add the panel that contains the log entries
|
||||
parentBody.add(gameLog, "w 10:100%, h 100%");
|
||||
}
|
||||
|
||||
public void resetNewDraft() {
|
||||
// Should we store the draft?
|
||||
gameLog.reset();
|
||||
editorLogEntries.clear();
|
||||
}
|
||||
|
||||
public void updateConsole() {
|
||||
gameLog.updateUI();
|
||||
}
|
||||
|
||||
public void addLogEntry(String entry) {
|
||||
gameLog.addLogEntry(entry);
|
||||
this.editorLogEntries.add(entry);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package forge;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.gamemodes.limited.IDraftLog;
|
||||
import forge.gamemodes.limited.LimitedPlayer;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import forge.deck.CardPool;
|
||||
@@ -32,6 +34,16 @@ public class BoosterDraftTest implements IBoosterDraft {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitedPlayer[] getOpposingPlayers() {
|
||||
return new LimitedPlayer[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitedPlayer getHumanPlayer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardPool nextChoice() {
|
||||
this.n--;
|
||||
@@ -69,4 +81,14 @@ public class BoosterDraftTest implements IBoosterDraft {
|
||||
public boolean isPileDraft() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogEntry(IDraftLog draftingProcess) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDraftLog getDraftLog() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,33 +635,6 @@
|
||||
1 Wayfaring Temple|RTR
|
||||
1 Wild Beastmaster|RTR
|
||||
|
||||
[CNS Draft Matters]
|
||||
#1 Advantageous Proclamation|CNS
|
||||
#1 AEther Searcher|CNS
|
||||
#1 Agent of Acquisitions|CNS
|
||||
#1 Backup Plan|CNS
|
||||
1 Brago's Favor|CNS
|
||||
#1 Canal Dredger|CNS
|
||||
#1 Cogwork Grinder|CNS
|
||||
#1 Cogwork Librarian|CNS
|
||||
#1 Cogwork Spy|CNS
|
||||
#1 Cogwork Tracker|CNS
|
||||
#1 Deal Broker|CNS
|
||||
#1 Double Stroke|CNS
|
||||
1 Immediate Action|CNS
|
||||
#1 Iterative Analysis|CNS
|
||||
#1 Lore Seeker|CNS
|
||||
#1 Lurking Automaton|CNS
|
||||
1 Muzzio's Preparations|CNS
|
||||
#1 Paliano, the High City|CNS
|
||||
#1 Power Play|CNS
|
||||
1 Secret Summoning|CNS
|
||||
1 Secrets of Paradise|CNS
|
||||
#1 Sentinel Dispatch|CNS
|
||||
#1 Unexpected Potential|CNS
|
||||
#1 Whispergear Sneak|CNS
|
||||
#1 Worldknit|CNS
|
||||
|
||||
[M15 Sample Cards]
|
||||
1 Aegis Angel|M15
|
||||
1 Cancel|M15
|
||||
@@ -965,21 +938,6 @@ Strip Mine|EXP
|
||||
Tectonic Edge|EXP
|
||||
Wasteland|EXP
|
||||
|
||||
|
||||
[CN2 Draft Matters]
|
||||
Adriana's Valor
|
||||
Assemble the Rank and Vile
|
||||
Echoing Boon
|
||||
#Emissary's Ploy
|
||||
Hired Heist
|
||||
Hold the Perimeter
|
||||
Hymn of the Wilds
|
||||
Incendiary Dissent
|
||||
Natural Unity
|
||||
#Sovereign's Realm
|
||||
Summoner's Bond
|
||||
Weight Advantage
|
||||
|
||||
[MPS Amonkhet Invocations]
|
||||
Austere Command|MPS_AKH
|
||||
Aven Mindcensor|MPS_AKH
|
||||
@@ -1483,24 +1441,6 @@ Kenrith's Transformation|ELD|2
|
||||
Improbable Alliance|ELD|2
|
||||
Inspiring Veteran|ELD|2
|
||||
|
||||
[CN2 Not In Normal Slots]
|
||||
Adriana's Valor
|
||||
Assemble the Rank and Vile
|
||||
Echoing Boon
|
||||
#Emissary's Ploy
|
||||
Hired Heist
|
||||
Hold the Perimeter
|
||||
Hymn of the Wilds
|
||||
Incendiary Dissent
|
||||
Natural Unity
|
||||
#Sovereign's Realm
|
||||
Summoner's Bond
|
||||
Weight Advantage
|
||||
Kaya, Ghost Assassin|CN2|2
|
||||
|
||||
[CN2 Foil Kaya]
|
||||
Kaya, Ghost Assassin|CN2|2
|
||||
|
||||
[JMP Above the Clouds 1]
|
||||
1 Warden of Evos Isle|JMP
|
||||
1 Inniaz, the Gale Force|JMP
|
||||
|
||||
9
forge-gui/res/cardsfolder/c/custodi_peacekeeper.txt
Normal file
9
forge-gui/res/cardsfolder/c/custodi_peacekeeper.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Name:Custodi Peacekeeper
|
||||
ManaCost:2 W
|
||||
Types:Creature Human Cleric
|
||||
PT:2/3
|
||||
Draft:Reveal CARDNAME as you draft it.
|
||||
Draft:Note how many cards you've drafted this draft round, including CARDNAME.
|
||||
A:AB$ Tap | Cost$ W T | ValidTgts$ Creature.powerLEX | TgtPrompt$ Tap target creature with power less than or equal to the highest number you noted for cards named Custodi Peacekeeper. | SpellDescription$ Tap target creature with power less than or equal to the highest number you noted for cards named Custodi Peacekeeper.
|
||||
SVar:X:Count$DraftNotesHighest.Custodi Peacekeeper
|
||||
Oracle:Reveal Custodi Peacekeeper as you draft it and note how many cards you’ve drafted this draft round, including Custodi Peacekeeper.\n{W}, {T}: Tap target creature with power less than or equal to the highest number you noted for cards named Custodi Peacekeeper.
|
||||
8
forge-gui/res/cardsfolder/g/garbage_fire.txt
Normal file
8
forge-gui/res/cardsfolder/g/garbage_fire.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name:Garbage Fire
|
||||
ManaCost:2 R
|
||||
Types:Instant
|
||||
Draft:Reveal CARDNAME as you draft it.
|
||||
Draft:Note how many cards you've drafted this draft round, including CARDNAME.
|
||||
A:SP$ DealDamage | ValidTgts$ Creature | NumDmg$ X | Description$ CARDNAME deals damage to target creature equal to the highest number you noted for cards named Garbage Fire.
|
||||
SVar:X:Count$DraftNotesHighest.Garbage Fire
|
||||
Oracle:Reveal Garbage Fire as you draft it and note how many cards you’ve drafted this draft round, including Garbage Fire.\nGarbage Fire deals damage to target creature equal to the highest number you noted for cards named Garbage Fire.
|
||||
9
forge-gui/res/cardsfolder/l/lurking_automaton.txt
Normal file
9
forge-gui/res/cardsfolder/l/lurking_automaton.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Name:Lurking Automaton
|
||||
ManaCost:5
|
||||
Types:Artifact Creature Construct
|
||||
PT:0/0
|
||||
Draft:Reveal CARDNAME as you draft it.
|
||||
Draft:Note how many cards you've drafted this draft round, including CARDNAME.
|
||||
K:etbCounter:P1P1:X:no Condition:CARDNAME enters the battlefield with X +1/+1 counters on it, where X is the highest number you noted for cards named Lurking Automaton.
|
||||
SVar:X:Count$DraftNotesHighest.Lurking Automaton
|
||||
Oracle:Reveal Lurking Automaton as you draft it and note how many cards you’ve drafted this draft round, including Lurking Automaton.\nLurking Automaton enters the battlefield with X +1/+1 counters on it, where X is the highest number you noted for cards named Lurking Automaton.
|
||||
10
forge-gui/res/cardsfolder/p/pyretic_hunter.txt
Normal file
10
forge-gui/res/cardsfolder/p/pyretic_hunter.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Name:Pyretic Hunter
|
||||
ManaCost:4 R
|
||||
Types:Creature Elemental Cat
|
||||
PT:0/0
|
||||
Draft:Reveal CARDNAME as you draft it.
|
||||
Draft:Note how many cards you've drafted this draft round, including CARDNAME.
|
||||
K:etbCounter:P1P1:X:no Condition:CARDNAME enters the battlefield with X +1/+1 counters on it, where X is the highest number you noted for cards named Pyretic Hunter.
|
||||
K:Menace
|
||||
SVar:X:Count$DraftNotesHighest.Pyretic Hunter
|
||||
Oracle:Reveal Pyretic Hunter as you draft it and note how many cards you’ve drafted this draft round, including Pyretic Hunter.\nMenace (This creature can’t be blocked except by two or more creatures.)\nPyretic Hunter enters the battlefield with X +1/+1 counters on it, where X is the highest number you noted for cards named Pyretic Hunter.
|
||||
@@ -56,7 +56,7 @@
|
||||
#55|He Who Hungers|R|CHK
|
||||
#56|Ghostly Prison|U|CHK
|
||||
#57|Samurai of the Pale Curtain|U|CHK
|
||||
#58|Soratami Mirror Guard|C|CHK
|
||||
#58|Soratami Mirror-Guard|C|CHK
|
||||
#59|Reciprocate|U|CHK
|
||||
#60|Sensei's Divining Top|U|CHK
|
||||
#61|Frostwielder|C|CHK
|
||||
@@ -108,7 +108,7 @@
|
||||
#107|Orochi Sustainer|C|CHK
|
||||
#108|Blood Speaker|U|CHK
|
||||
#109|Brutal Deceiver|C|CHK
|
||||
#110|Ember Fist Zubera|C|CHK
|
||||
#110|Ember-Fist Zubera|C|CHK
|
||||
#111|Kami of Old Stone|U|CHK
|
||||
#112|Budoka Gardener|R|CHK
|
||||
#113|Indomitable Will|C|CHK
|
||||
@@ -186,7 +186,7 @@
|
||||
#185|Distress|C|CHK
|
||||
#186|Myojin of Night's Reach|R|CHK
|
||||
#187|Eerie Procession|U|CHK
|
||||
#188|Battle Mad Ronin|C|CHK
|
||||
#188|Battle-Mad Ronin|C|CHK
|
||||
#189|Cranial Extraction|R|CHK
|
||||
#190|Orochi Leafcaller|C|CHK
|
||||
#191|Ethereal Haze|C|CHK
|
||||
|
||||
@@ -5,7 +5,7 @@ Name=Conspiracy: Take the Crown
|
||||
Code2=CN2
|
||||
Type=Draft
|
||||
BoosterCovers=3
|
||||
Booster=10 Common:!fromSheet("CN2 Not In Normal Slots"), 3 Uncommon:!fromSheet("CN2 Not In Normal Slots"), 1 RareMythic:!fromSheet("CN2 Not In Normal Slots"), 1 fromSheet("CN2 Draft Matters")
|
||||
Booster=10 Common:!fromSheet("CN2 Draft Matters"), 3 Uncommon:!fromSheet("CN2 Draft Matters"), 1 RareMythic:!fromSheet("CN2 Draft Matters"), 1 fromSheet("CN2 Draft Matters")
|
||||
AdditionalSheetForFoils=fromSheet("CN2 Foil Kaya")
|
||||
ScryfallCode=CN2
|
||||
|
||||
@@ -231,8 +231,30 @@ ScryfallCode=CN2
|
||||
219 R Exotic Orchard @Steven Belledin
|
||||
220 U Rogue's Passage @Christine Choi
|
||||
221 U Shimmering Grotto @Cliff Childs
|
||||
|
||||
[promo]
|
||||
222 M Kaya, Ghost Assassin @Chris Rallis
|
||||
|
||||
[Draft Matters]
|
||||
Adriana's Valor
|
||||
Assemble the Rank and Vile
|
||||
Custodi Peacekeeper
|
||||
Echoing Boon
|
||||
#Emissary's Ploy
|
||||
Garbage Fire
|
||||
Hired Heist
|
||||
Hold the Perimeter
|
||||
Hymn of the Wilds
|
||||
Incendiary Dissent
|
||||
Natural Unity
|
||||
Pyretic Hunter
|
||||
#Sovereign's Realm
|
||||
Summoner's Bond
|
||||
Weight Advantage
|
||||
|
||||
[Foil Kaya]
|
||||
Kaya, Ghost Assassin|CN2|2
|
||||
|
||||
[tokens]
|
||||
w_1_1_soldier
|
||||
w_1_2_soldier_defender
|
||||
|
||||
@@ -220,6 +220,33 @@ ScryfallCode=CNS
|
||||
209 U Quicksand @Matt Stewart
|
||||
210 R Reflecting Pool @Fred Fields
|
||||
|
||||
[Draft Matters]
|
||||
#1 Advantageous Proclamation|CNS
|
||||
#1 AEther Searcher|CNS
|
||||
#1 Agent of Acquisitions|CNS
|
||||
#1 Backup Plan|CNS
|
||||
1 Brago's Favor|CNS
|
||||
#1 Canal Dredger|CNS
|
||||
#1 Cogwork Grinder|CNS
|
||||
#1 Cogwork Librarian|CNS
|
||||
#1 Cogwork Spy|CNS
|
||||
#1 Cogwork Tracker|CNS
|
||||
#1 Deal Broker|CNS
|
||||
#1 Double Stroke|CNS
|
||||
1 Immediate Action|CNS
|
||||
#1 Iterative Analysis|CNS
|
||||
#1 Lore Seeker|CNS
|
||||
1 Lurking Automaton|CNS
|
||||
1 Muzzio's Preparations|CNS
|
||||
#1 Paliano, the High City|CNS
|
||||
#1 Power Play|CNS
|
||||
1 Secret Summoning|CNS
|
||||
1 Secrets of Paradise|CNS
|
||||
#1 Sentinel Dispatch|CNS
|
||||
#1 Unexpected Potential|CNS
|
||||
#1 Whispergear Sneak|CNS
|
||||
#1 Worldknit|CNS
|
||||
|
||||
[tokens]
|
||||
w_1_1_spirit_flying
|
||||
b_x_x_demon_flying
|
||||
|
||||
@@ -870,6 +870,7 @@ ttRemove4ofcard=Remove up to 4 of selected card to current deck
|
||||
lblAddBasicLands=Add Basic Lands
|
||||
ttAddBasicLands=Add basic lands to the deck
|
||||
lblCardCatalog=Card Catalog
|
||||
lblEditorLog=Editor Log
|
||||
lblJumptoprevioustable=Jump to previous table
|
||||
lblJumptopnexttable=Jump to next table
|
||||
lblJumptotextfilter=Jump to text filter
|
||||
|
||||
@@ -62,7 +62,9 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
private static final int N_PLAYERS = 8;
|
||||
public static final String FILE_EXT = ".draft";
|
||||
private final List<LimitedPlayer> players = new ArrayList<>();
|
||||
private LimitedPlayer localPlayer;
|
||||
private final LimitedPlayer localPlayer;
|
||||
|
||||
private IDraftLog draftLog = null;
|
||||
|
||||
private String doublePickDuringDraft = ""; // "FirstPick" or "Always"
|
||||
protected int nextBoosterGroup = 0;
|
||||
@@ -264,12 +266,16 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
}
|
||||
|
||||
protected BoosterDraft(final LimitedPoolType draftType) {
|
||||
this(draftType, N_PLAYERS);
|
||||
}
|
||||
|
||||
protected BoosterDraft(final LimitedPoolType draftType, int numPlayers) {
|
||||
this.draftFormat = draftType;
|
||||
|
||||
localPlayer = new LimitedPlayer(0);
|
||||
localPlayer = new LimitedPlayer(0, this);
|
||||
players.add(localPlayer);
|
||||
for (int i = 1; i < N_PLAYERS; i++) {
|
||||
players.add(new LimitedPlayerAI(i));
|
||||
for (int i = 1; i < numPlayers; i++) {
|
||||
players.add(new LimitedPlayerAI(i, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +284,16 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogEntry(IDraftLog draftingProcess) {
|
||||
draftLog = draftingProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDraftLog getDraftLog() {
|
||||
return draftLog;
|
||||
}
|
||||
|
||||
private void setupCustomDraft(final CustomLimited draft) {
|
||||
final ItemPool<PaperCard> dPool = draft.getCardPool();
|
||||
if (dPool == null) {
|
||||
@@ -374,6 +390,9 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
for (LimitedPlayer pl : this.players) {
|
||||
pl.newPack();
|
||||
}
|
||||
if (this.getDraftLog() != null) {
|
||||
this.getDraftLog().addLogEntry("Round " + this.nextBoosterGroup + " is starting...");
|
||||
}
|
||||
this.currentBoosterSize = firstPlayer.packQueue.peek().size();
|
||||
return true;
|
||||
}
|
||||
@@ -387,6 +406,16 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
return decks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitedPlayer[] getOpposingPlayers() {
|
||||
return this.players.toArray(new LimitedPlayer[7]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitedPlayer getHumanPlayer() {
|
||||
return this.localPlayer;
|
||||
}
|
||||
|
||||
public void passPacks() {
|
||||
// Alternate direction of pack passing
|
||||
int adjust = this.nextBoosterGroup % 2 == 1 ? 1 : -1;
|
||||
@@ -404,8 +433,11 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
continue;
|
||||
|
||||
if (!passingPack.isEmpty()) {
|
||||
if (passingPack.size() == 1) {
|
||||
// TODO Canal Dredger for passing a pack with a single card in it
|
||||
|
||||
}
|
||||
|
||||
int passTo = (i + adjust + N_PLAYERS) % N_PLAYERS;
|
||||
this.players.get(passTo).receiveOpenedPack(passingPack);
|
||||
this.players.get(passTo).adjustPackNumber(adjust, packsInDraft);
|
||||
|
||||
@@ -37,9 +37,13 @@ public interface IBoosterDraft {
|
||||
boolean hasNextChoice();
|
||||
boolean isRoundOver();
|
||||
Deck[] getDecks(); // size 7, all the computers decks
|
||||
LimitedPlayer[] getOpposingPlayers(); // size 7, all the computers
|
||||
LimitedPlayer getHumanPlayer();
|
||||
|
||||
CardEdition[] LAND_SET_CODE = { null };
|
||||
String[] CUSTOM_RANKINGS_FILE = { null };
|
||||
boolean isPileDraft();
|
||||
|
||||
void setLogEntry(IDraftLog draftingProcess);
|
||||
IDraftLog getDraftLog();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package forge.gamemodes.limited;
|
||||
|
||||
public interface IDraftLog {
|
||||
public void addLogEntry(String message);
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package forge.gamemodes.limited;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
//import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
import java.util.*;
|
||||
//import forge.gamemodes.limited.powers.DraftPower;
|
||||
|
||||
public class LimitedPlayer {
|
||||
@@ -21,31 +21,43 @@ public class LimitedPlayer {
|
||||
protected Queue<List<PaperCard>> packQueue;
|
||||
protected Queue<List<PaperCard>> unopenedPacks;
|
||||
|
||||
// WIP - Draft Matters cards
|
||||
/*
|
||||
private static int CantDraftThisRound = 1,
|
||||
SpyNextCardDrafted = 1 << 1,
|
||||
ReceiveLastCard = 1 << 2,
|
||||
CanRemoveAfterDraft = 1 << 3,
|
||||
CanTradeAfterDraft = 1 << 4;
|
||||
private static final int CantDraftThisRound = 1;
|
||||
private static final int SpyNextCardDrafted = 1 << 1;
|
||||
private static final int ReceiveLastCard = 1 << 2;
|
||||
private static final int CanRemoveAfterDraft = 1 << 3;
|
||||
private static final int CanTradeAfterDraft = 1 << 4;
|
||||
|
||||
private static int MAXFLAGS = CantDraftThisRound | ReceiveLastCard | CanRemoveAfterDraft | SpyNextCardDrafted
|
||||
private static final int MAXFLAGS = CantDraftThisRound | ReceiveLastCard | CanRemoveAfterDraft | SpyNextCardDrafted
|
||||
| CanTradeAfterDraft;
|
||||
|
||||
private final int playerFlags = 0;
|
||||
|
||||
private int playerFlags = 0;
|
||||
private final List<PaperCard> faceUp = Lists.newArrayList();
|
||||
private final List<PaperCard> revealed = Lists.newArrayList();
|
||||
private final Map<String, List<String>> noted = new HashMap<>();
|
||||
//private Map<DraftPower, Integer> powers = new HashMap<>();
|
||||
|
||||
private List<PaperCard> revealed = Lists.newArrayList();
|
||||
private Map<String, List<Object>> noted = new HashMap<>();
|
||||
private Map<DraftPower, Integer> powers = new HashMap<>();
|
||||
*/
|
||||
IBoosterDraft draft = null;
|
||||
|
||||
public LimitedPlayer(int seatingOrder) {
|
||||
public LimitedPlayer(int seatingOrder, IBoosterDraft draft) {
|
||||
order = seatingOrder;
|
||||
deck = new Deck();
|
||||
|
||||
packQueue = new LinkedList<>();
|
||||
unopenedPacks = new LinkedList<>();
|
||||
this.draft = draft;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getDraftNotes() {
|
||||
return noted;
|
||||
}
|
||||
|
||||
public Map<String, String> getSerializedDraftNotes() {
|
||||
Map<String, String> serialized = new HashMap<>();
|
||||
for (Map.Entry<String, List<String>> entry : noted.entrySet()) {
|
||||
serialized.put(entry.getKey(), TextUtil.join(entry.getValue(), ","));
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
public PaperCard chooseCard() {
|
||||
@@ -72,16 +84,38 @@ public class LimitedPlayer {
|
||||
pool.add(bestPick);
|
||||
draftedThisRound++;
|
||||
|
||||
// TODO Note Lurking Automaton
|
||||
if (bestPick.getRules().getMainPart().getDraftActions() == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Draft Actions
|
||||
Iterable<String> draftActions = bestPick.getRules().getMainPart().getDraftActions();
|
||||
if (Iterables.contains(draftActions, "Reveal CARDNAME as you draft it.")) {
|
||||
revealed.add(bestPick);
|
||||
|
||||
if (Iterables.contains(draftActions, "Note how many cards you've drafted this draft round, including CARDNAME.")) {
|
||||
List<String> note = noted.computeIfAbsent(bestPick.getName(), k -> Lists.newArrayList());
|
||||
note.add(String.valueOf(draftedThisRound));
|
||||
|
||||
addLog(name() + " revealed " + bestPick.getName() + " and noted " + draftedThisRound + " cards drafted this round.");
|
||||
} else {
|
||||
addLog(name() + " revealed " + bestPick.getName() + " as they drafted it.");
|
||||
}
|
||||
}
|
||||
|
||||
// Colors
|
||||
// TODO Note Paliano, the High City
|
||||
// TODO Note Aether Searcher
|
||||
// TODO Note Custodi Peacepeeper
|
||||
// TODO Note Regicide
|
||||
// TODO Note Paliano Vanguard
|
||||
// TODO Note Garbage Fire
|
||||
// TODO Note Aether Searcher (for the next card)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addLog(String message) {
|
||||
this.draft.getDraftLog().addLogEntry(message);
|
||||
}
|
||||
|
||||
public List<PaperCard> nextChoice() {
|
||||
return packQueue.peek();
|
||||
}
|
||||
@@ -107,6 +141,14 @@ public class LimitedPlayer {
|
||||
packQueue.add(pack);
|
||||
}
|
||||
|
||||
public String name() {
|
||||
if (this instanceof LimitedPlayerAI) {
|
||||
return "Player[" + order + "]";
|
||||
}
|
||||
|
||||
return "You";
|
||||
}
|
||||
|
||||
/*
|
||||
public void addSingleBoosterPack(boolean random) {
|
||||
// TODO Lore Seeker
|
||||
|
||||
@@ -12,8 +12,8 @@ import forge.localinstance.properties.ForgePreferences;
|
||||
public class LimitedPlayerAI extends LimitedPlayer {
|
||||
protected DeckColors deckCols;
|
||||
|
||||
public LimitedPlayerAI(int seatingOrder) {
|
||||
super(seatingOrder);
|
||||
public LimitedPlayerAI(int seatingOrder, BoosterDraft draft) {
|
||||
super(seatingOrder, draft);
|
||||
deckCols = new DeckColors();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user