mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Merge remote-tracking branch 'upstream/master' into collector-number-in-card-list-and-card-db-refactoring
This commit is contained in:
@@ -21,7 +21,7 @@ import forge.util.storage.StorageBase;
|
||||
|
||||
public class NetDeckCategory extends StorageBase<Deck> {
|
||||
public static final String PREFIX = "NET_DECK_";
|
||||
private static Map<String, NetDeckCategory> constructed, commander, brawl;
|
||||
private static Map<String, NetDeckCategory> constructed, commander, brawl, oathbreaker, tinyleaders;
|
||||
|
||||
private static Map<String, NetDeckCategory> loadCategories(String filename) {
|
||||
Map<String, NetDeckCategory> categories = new TreeMap<>();
|
||||
@@ -64,6 +64,18 @@ public class NetDeckCategory extends StorageBase<Deck> {
|
||||
}
|
||||
categories = brawl;
|
||||
break;
|
||||
case Oathbreaker:
|
||||
if (oathbreaker == null) {
|
||||
oathbreaker = loadCategories(ForgeConstants.NET_DECKS_OATHBREAKER_LIST_FILE);
|
||||
}
|
||||
categories = oathbreaker;
|
||||
break;
|
||||
case TinyLeaders:
|
||||
if (tinyleaders == null) {
|
||||
tinyleaders = loadCategories(ForgeConstants.NET_DECKS_TINYLEADERS_LIST_FILE);
|
||||
}
|
||||
categories = tinyleaders;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class BoosterDraft implements IBoosterDraft {
|
||||
protected boolean generateProduct() {
|
||||
switch (this.draftFormat) {
|
||||
case Full: // Draft from all cards in Forge
|
||||
final Supplier<List<PaperCard>> s = new UnOpenedProduct(SealedProduct.Template.genericBooster);
|
||||
final Supplier<List<PaperCard>> s = new UnOpenedProduct(SealedProduct.Template.genericDraftBooster);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
this.product.add(s);
|
||||
|
||||
@@ -107,7 +107,7 @@ public class CustomLimited extends DeckBase {
|
||||
slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0])));
|
||||
}
|
||||
} else
|
||||
slots = SealedProduct.Template.genericBooster.getSlots();
|
||||
slots = SealedProduct.Template.genericDraftBooster.getSlots();
|
||||
|
||||
final CustomLimited cd = new CustomLimited(data.get("Name"), slots);
|
||||
cd.landSetCode = data.get("LandSetCode");
|
||||
|
||||
@@ -164,7 +164,7 @@ public class SealedCardPoolGenerator {
|
||||
switch(poolType) {
|
||||
case Full:
|
||||
// Choose number of boosters
|
||||
if (!chooseNumberOfBoosters(new UnOpenedProduct(SealedProduct.Template.genericBooster))) {
|
||||
if (!chooseNumberOfBoosters(new UnOpenedProduct(SealedProduct.Template.genericDraftBooster))) {
|
||||
return;
|
||||
}
|
||||
landSetCode = CardEdition.Predicates.getRandomSetWithAllBasicLands(FModel.getMagicDb().getEditions()).getCode();
|
||||
@@ -209,7 +209,7 @@ public class SealedCardPoolGenerator {
|
||||
code = pieces[1];
|
||||
}
|
||||
|
||||
// Generate boosters
|
||||
// Generate draft boosters
|
||||
for(int i = 0; i < num; i++) {
|
||||
this.product.add(new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(code)));
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
||||
}
|
||||
|
||||
// Store some information about color costs to help with any mana choices
|
||||
if (colorNeeded == 0) { // only colorless left
|
||||
if (colorNeeded == 0) { // only colorless left
|
||||
if (saPaidFor.getHostCard() != null && saPaidFor.getHostCard().hasSVar("ManaNeededToAvoidNegativeEffect")) {
|
||||
String[] negEffects = saPaidFor.getHostCard().getSVar("ManaNeededToAvoidNegativeEffect").split(",");
|
||||
for (String negColor : negEffects) {
|
||||
|
||||
@@ -72,7 +72,6 @@ public class InputPayManaOfCostPayment extends InputPayMana {
|
||||
msg.append(messagePrefix).append("\n");
|
||||
}
|
||||
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT)) {
|
||||
// msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", ""));
|
||||
if (saPaidFor.isSpell()) {
|
||||
msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", "")).append("\n\n");
|
||||
} else {
|
||||
|
||||
@@ -126,7 +126,6 @@ public class InputProxy implements Observer {
|
||||
|
||||
public final boolean selectCard(final CardView cardView, final List<CardView> otherCardViewsToSelect, final ITriggerEvent triggerEvent) {
|
||||
final Input inp = getInput();
|
||||
//System.out.println("Selectcard " +cardView + " input: " +inp);
|
||||
if (inp != null) {
|
||||
final Card card = getCard(cardView);
|
||||
if (card != null) {
|
||||
|
||||
@@ -32,7 +32,7 @@ public class InputSelectEntitiesFromList<T extends GameEntity> extends InputSele
|
||||
public InputSelectEntitiesFromList(final PlayerControllerHuman controller, final int min, final int max, final FCollectionView<T> validChoices0, final SpellAbility sa0) {
|
||||
super(controller, Math.min(min, validChoices0.size()), Math.min(max, validChoices0.size()), sa0);
|
||||
validChoices = validChoices0;
|
||||
if (min > validChoices.size()) { // pfps does this really do anything useful??
|
||||
if (min > validChoices.size()) { // pfps does this really do anything useful??
|
||||
System.out.println(String.format("Trying to choose at least %d things from a list with only %d things!", min, validChoices.size()));
|
||||
}
|
||||
ArrayList<CardView> vCards = new ArrayList<>();
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.game.GameEntity;
|
||||
@@ -129,10 +128,10 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
||||
"(Targeting ERROR)", "");
|
||||
showMessage(message, sa.getView());
|
||||
|
||||
if (sa.isDividedAsYouChoose() && sa.getMinTargets() == 0 && sa.getTargets().size() == 0) {
|
||||
if ((divisionValues != null && !divisionValues.isEmpty()) && sa.getMinTargets() == 0 && sa.getTargets().size() == 0) {
|
||||
// extra logic for Divided with min targets = 0, should only work if num targets are 0 too
|
||||
getController().getGui().updateButtons(getOwner(), true, true, false);
|
||||
} else if (!sa.isMinTargetChosen() || sa.isDividedAsYouChoose()) {
|
||||
} else if (!sa.isMinTargetChosen() || (divisionValues != null && !divisionValues.isEmpty())){
|
||||
// If reached Minimum targets, enable OK button
|
||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
||||
// Player has to click on a target
|
||||
@@ -280,7 +279,7 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sa.isDividedAsYouChoose()) {
|
||||
if ((divisionValues != null && !divisionValues.isEmpty())) {
|
||||
Boolean val = onDividedAsYouChoose(card);
|
||||
if (val != null) {
|
||||
return val;
|
||||
@@ -322,7 +321,7 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sa.isDividedAsYouChoose()) {
|
||||
if ((divisionValues != null && !divisionValues.isEmpty())) {
|
||||
Boolean val = onDividedAsYouChoose(player);
|
||||
if (val != null) {
|
||||
return;
|
||||
@@ -332,57 +331,25 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
||||
}
|
||||
|
||||
protected Boolean onDividedAsYouChoose(GameObject go) {
|
||||
if (divisionValues != null) {
|
||||
if (divisionValues.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String apiBasedMessage = "Distribute how much to ";
|
||||
if (sa.getApi() == ApiType.DealDamage) {
|
||||
apiBasedMessage = "Select how much damage to deal to ";
|
||||
}
|
||||
else if (sa.getApi() == ApiType.PreventDamage) {
|
||||
apiBasedMessage = "Select how much damage to prevent to ";
|
||||
}
|
||||
else if (sa.getApi() == ApiType.PutCounter) {
|
||||
apiBasedMessage = "Select how many counters to distribute to ";
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(apiBasedMessage);
|
||||
sb.append(go.toString());
|
||||
final Integer chosen = getController().getGui().oneOrNone(sb.toString(), Lists.newArrayList(divisionValues));
|
||||
if (chosen == null) {
|
||||
return true; //still return true since there was a valid choice
|
||||
}
|
||||
divisionValues.remove(chosen);
|
||||
sa.addDividedAllocation(go, chosen);
|
||||
} else {
|
||||
final int stillToDivide = sa.getStillToDivide();
|
||||
int allocatedPortion = 0;
|
||||
// allow allocation only if the max targets isn't reached and there are more candidates
|
||||
if ((sa.getTargets().size() + 1 < sa.getMaxTargets()) && (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
||||
final ImmutableList.Builder<Integer> choices = ImmutableList.builder();
|
||||
for (int i = 1; i <= stillToDivide; i++) {
|
||||
choices.add(Integer.valueOf(i));
|
||||
}
|
||||
String apiBasedMessage = "Distribute how much to ";
|
||||
if (sa.getApi() == ApiType.DealDamage) {
|
||||
apiBasedMessage = "Select how much damage to deal to ";
|
||||
} else if (sa.getApi() == ApiType.PreventDamage) {
|
||||
apiBasedMessage = "Select how much damage to prevent to ";
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(apiBasedMessage);
|
||||
sb.append(go.toString());
|
||||
final Integer chosen = getController().getGui().oneOrNone(sb.toString(), choices.build());
|
||||
if (null == chosen) {
|
||||
return true;
|
||||
}
|
||||
allocatedPortion = chosen;
|
||||
} else { // otherwise assign the rest of the damage/protection
|
||||
allocatedPortion = stillToDivide;
|
||||
}
|
||||
sa.addDividedAllocation(go, allocatedPortion);
|
||||
String apiBasedMessage = "Distribute how much to ";
|
||||
if (sa.getApi() == ApiType.DealDamage) {
|
||||
apiBasedMessage = "Select how much damage to deal to ";
|
||||
}
|
||||
else if (sa.getApi() == ApiType.PreventDamage) {
|
||||
apiBasedMessage = "Select how much damage to prevent to ";
|
||||
}
|
||||
else if (sa.getApi() == ApiType.PutCounter) {
|
||||
apiBasedMessage = "Select how many counters to distribute to ";
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(apiBasedMessage);
|
||||
sb.append(go.toString());
|
||||
final Integer chosen = getController().getGui().oneOrNone(sb.toString(), Lists.newArrayList(divisionValues));
|
||||
if (chosen == null) {
|
||||
return true; //still return true since there was a valid choice
|
||||
}
|
||||
divisionValues.remove(chosen);
|
||||
sa.addDividedAllocation(go, chosen);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -419,7 +386,8 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
||||
}
|
||||
|
||||
private boolean hasAllTargets() {
|
||||
return sa.isMaxTargetChosen() || (sa.isDividedAsYouChoose() && sa.getStillToDivide() == 0);
|
||||
return sa.isMaxTargetChosen() || (divisionValues != null && sa.getStillToDivide() == 0)
|
||||
|| (sa.isDividedAsYouChoose() && sa.getTargets().size() == sa.getStillToDivide());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -207,7 +207,7 @@ public class NetGuiGame extends AbstractGuiGame {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<GameEntityView, Integer> assignGenericAmount(final CardView effectSource, final Map<GameEntityView, Integer> targets, final int amount, final boolean atLeastOne, final String amountLabel) {
|
||||
public Map<Object, Integer> assignGenericAmount(final CardView effectSource, final Map<Object, Integer> targets, final int amount, final boolean atLeastOne, final String amountLabel) {
|
||||
return sendAndWait(ProtocolMethod.divideShield, effectSource, targets, amount, atLeastOne, amountLabel);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,20 +69,23 @@ public final class BoosterUtils {
|
||||
};
|
||||
|
||||
private static final GameFormat.Collection formats = FModel.getFormats();
|
||||
private static final Predicate<CardEdition> filterExt = formats.getExtended().editionLegalPredicate;
|
||||
private static final Predicate<CardEdition> filterPioneer = formats.getPioneer().editionLegalPredicate;
|
||||
private static final Predicate<CardEdition> filterModern= formats.getModern().editionLegalPredicate;
|
||||
|
||||
/** The filter t2booster. */
|
||||
private static final Predicate<CardEdition> filterT2booster = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
private static final Predicate<CardEdition> filterStandard = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
formats.getStandard().editionLegalPredicate);
|
||||
|
||||
/** The filter ext but t2. */
|
||||
private static final Predicate<CardEdition> filterExtButT2 = Predicates.and(
|
||||
private static final Predicate<CardEdition> filterPioneerNotStandard = Predicates.and(
|
||||
CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
Predicates.and(filterExt, formats.getStandard().editionLegalPredicate));
|
||||
Predicates.and(filterPioneer, Predicates.not(formats.getStandard().editionLegalPredicate)));
|
||||
|
||||
private static final Predicate<CardEdition> filterModernNotPioneer = Predicates.and(
|
||||
CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
Predicates.and(filterModern, Predicates.not(filterPioneer)));
|
||||
|
||||
/** The filter not ext. */
|
||||
private static final Predicate<CardEdition> filterNotExt = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
Predicates.not(filterExt));
|
||||
private static final Predicate<CardEdition> filterNotModern = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
Predicates.not(filterModern));
|
||||
|
||||
/**
|
||||
* Gets the quest starter deck.
|
||||
@@ -169,7 +172,19 @@ public final class BoosterUtils {
|
||||
return generateRandomBoosterPacks(quantity, isLegalInQuestFormat(questController.getFormat()));
|
||||
} else {
|
||||
final int rollD100 = MyRandom.getRandom().nextInt(100);
|
||||
return generateRandomBoosterPacks(quantity, rollD100 < 40 ? filterT2booster : (rollD100 < 75 ? filterExtButT2 : filterNotExt));
|
||||
// 30% Standard, 20% Pioneer, pre-standard -> 20% Modern, pre-pioneer -> 30% Pre-modern
|
||||
Predicate<CardEdition> rolledFilter;
|
||||
if (rollD100 < 30) {
|
||||
rolledFilter = filterStandard;
|
||||
} else if (rollD100 < 50) {
|
||||
rolledFilter = filterPioneerNotStandard;
|
||||
} else if (rollD100 < 70) {
|
||||
rolledFilter = filterModernNotPioneer;
|
||||
} else {
|
||||
rolledFilter = filterNotModern;
|
||||
}
|
||||
|
||||
return generateRandomBoosterPacks(quantity, rolledFilter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
@@ -589,7 +590,15 @@ public class QuestWinLoseController {
|
||||
final IUnOpenedProduct product = new UnOpenedProduct(getBoosterTemplate(), cards);
|
||||
cardsWon = product.get();
|
||||
} else {
|
||||
final IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode()));
|
||||
final IUnOpenedProduct product;
|
||||
List<String> boosterTypes = Lists.newArrayList(chooseEd.getAvailableBoosterTypes());
|
||||
String setAffix = "";
|
||||
String type = SGuiChoose.one("Which booster type do you choose?", boosterTypes);
|
||||
if (!type.equals("Draft")) {
|
||||
setAffix = type;
|
||||
}
|
||||
product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode() + setAffix));
|
||||
|
||||
cardsWon = product.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -231,15 +231,10 @@ public class QuestWorld implements Comparable<QuestWorld>{
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(QuestWorld other) {
|
||||
if (null == other) {
|
||||
if (null == other)
|
||||
return 1;
|
||||
}
|
||||
if (name == other.name) {
|
||||
return 0;
|
||||
}
|
||||
if (null == name) {
|
||||
return -1;
|
||||
}
|
||||
if (this.name == null)
|
||||
return -1; // dummy, no format!
|
||||
return name.compareTo(other.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public final class GameFormatQuest extends GameFormat {
|
||||
public GameFormatQuest(final GameFormat toCopy, boolean allowSetUnlocks) {
|
||||
super(toCopy.getName(), toCopy.getEffectiveDate(), toCopy.getAllowedSetCodes(), toCopy.getBannedCardNames(), toCopy.getRestrictedCards(),
|
||||
toCopy.isRestrictedLegendary(),toCopy.getAdditionalCards(), toCopy.getAllowedRarities(),
|
||||
toCopy.getIndex(), FormatType.Custom, FormatSubType.Custom);
|
||||
toCopy.getIndex(), FormatType.CUSTOM, FormatSubType.CUSTOM);
|
||||
allowUnlocks = allowSetUnlocks;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ public class CardDetailUtil {
|
||||
|
||||
public static String getCurrentColors(final CardStateView c) {
|
||||
ColorSet curColors = c.getColors();
|
||||
String strCurColors = "";
|
||||
String strCurColors = "";
|
||||
|
||||
if (curColors.hasWhite()) { strCurColors += "{W}"; }
|
||||
if (curColors.hasBlue()) { strCurColors += "{U}"; }
|
||||
@@ -140,7 +140,7 @@ public class CardDetailUtil {
|
||||
|
||||
return strCurColors;
|
||||
}
|
||||
|
||||
|
||||
public static DetailColors getRarityColor(final CardRarity rarity) {
|
||||
switch (rarity) {
|
||||
case Uncommon:
|
||||
@@ -251,7 +251,7 @@ public class CardDetailUtil {
|
||||
origIdent = origCard != null ? getCurrentColors(origCard.isFaceDown() ? CardView.get(origCard).getState(false) : CardView.get(origCard).getCurrentState()) : "";
|
||||
} catch(Exception ex) {
|
||||
System.err.println("Unexpected behavior: card " + card.getName() + "[" + card.getId() + "] tripped an exception when trying to process current card colors.");
|
||||
}
|
||||
}
|
||||
isChanged = !curColors.equals(origIdent);
|
||||
}
|
||||
|
||||
@@ -477,6 +477,15 @@ public class CardDetailUtil {
|
||||
area.append(")");
|
||||
}
|
||||
|
||||
// dungeon room
|
||||
if (card.getCurrentRoom() != null && !card.getCurrentRoom().isEmpty()) {
|
||||
if (area.length() != 0) {
|
||||
area.append("\n");
|
||||
}
|
||||
area.append("(In room: ");
|
||||
area.append(card.getCurrentRoom()).append(")");
|
||||
}
|
||||
|
||||
// a card has something attached to it
|
||||
if (card.hasCardAttachments()) {
|
||||
if (area.length() != 0) {
|
||||
|
||||
@@ -69,7 +69,8 @@ public interface IGuiGame {
|
||||
void setPanelSelection(CardView hostCard);
|
||||
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
|
||||
Map<CardView, Integer> assignCombatDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
|
||||
Map<GameEntityView, Integer> assignGenericAmount(CardView effectSource, Map<GameEntityView, Integer> target, int amount, final boolean atLeastOne, final String amountLabel);
|
||||
// The Object passed should be GameEntityView for most case. Can be Byte for "generate mana of any combination" effect
|
||||
Map<Object, Integer> assignGenericAmount(CardView effectSource, Map<Object, Integer> target, int amount, final boolean atLeastOne, final String amountLabel);
|
||||
|
||||
void message(String message);
|
||||
void message(String message, String title);
|
||||
|
||||
@@ -59,6 +59,8 @@ public interface IDevModeCheats {
|
||||
|
||||
void planeswalkTo();
|
||||
|
||||
void askAI();
|
||||
|
||||
/**
|
||||
* Implementation of {@link IDevModeCheats} that disallows cheating by
|
||||
* performing no action whatsoever when any of its methods is called.
|
||||
@@ -141,6 +143,9 @@ public interface IDevModeCheats {
|
||||
@Override
|
||||
public void removeCardsFromGame() {
|
||||
}
|
||||
@Override
|
||||
public void askAI() {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -48,6 +48,8 @@ public final class ForgeConstants {
|
||||
public static final String NET_DECKS_LIST_FILE = LISTS_DIR + "net-decks.txt";
|
||||
public static final String NET_DECKS_COMMANDER_LIST_FILE = LISTS_DIR + "net-decks-commander.txt";
|
||||
public static final String NET_DECKS_BRAWL_LIST_FILE = LISTS_DIR + "net-decks-brawl.txt";
|
||||
public static final String NET_DECKS_OATHBREAKER_LIST_FILE = LISTS_DIR + "net-decks-oathbreaker.txt";
|
||||
public static final String NET_DECKS_TINYLEADERS_LIST_FILE = LISTS_DIR + "net-decks-tinyleaders.txt";
|
||||
public static final String BORDERLESS_CARD_LIST_FILE = LISTS_DIR + "borderlessCardList.txt";
|
||||
public static final String SKINS_LIST_FILE = LISTS_DIR + "skinsList.txt";
|
||||
public static final String CJK_FONTS_LIST_FILE = LISTS_DIR + "font-list.txt";
|
||||
|
||||
@@ -166,7 +166,7 @@ public class MetaSet {
|
||||
|
||||
switch(type) {
|
||||
case Full:
|
||||
return new UnOpenedProduct(SealedProduct.Template.genericBooster);
|
||||
return new UnOpenedProduct(SealedProduct.Template.genericDraftBooster);
|
||||
|
||||
case Booster:
|
||||
return new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(data));
|
||||
@@ -179,7 +179,7 @@ public class MetaSet {
|
||||
|
||||
case JoinedSet:
|
||||
Predicate<PaperCard> predicate = IPaperCard.Predicates.printedInSets(data.split(" "));
|
||||
return new UnOpenedProduct(SealedProduct.Template.genericBooster, predicate);
|
||||
return new UnOpenedProduct(SealedProduct.Template.genericDraftBooster, predicate);
|
||||
|
||||
case Choose: return UnOpenedMeta.choose(data);
|
||||
case Random: return UnOpenedMeta.random(data);
|
||||
|
||||
@@ -1096,6 +1096,10 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
|
||||
if (c != null && c == 0) {
|
||||
return PaymentDecision.number(0);
|
||||
}
|
||||
|
||||
if (sameType) {
|
||||
final CardCollection list2 = typeList;
|
||||
typeList = CardLists.filter(typeList, new Predicate<Card>() {
|
||||
@@ -1109,9 +1113,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (c == 0) {
|
||||
return PaymentDecision.number(0);
|
||||
}
|
||||
|
||||
final CardCollection tapped = new CardCollection();
|
||||
while (c > 0) {
|
||||
final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, 1, 1, typeList, ability);
|
||||
|
||||
@@ -105,7 +105,6 @@ public class HumanPlay {
|
||||
|
||||
sa = AbilityUtils.addSpliceEffects(sa);
|
||||
|
||||
// System.out.println("Playing:" + sa.getDescription() + " of " + sa.getHostCard() + " new = " + newAbility);
|
||||
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
||||
if (!req.playAbility(true, false, false)) {
|
||||
if (flippedToCast && !castFaceDown) {
|
||||
@@ -674,7 +673,7 @@ public class HumanPlay {
|
||||
final Card offering = ability.getSacrificedAsOffering();
|
||||
offering.setUsedToPay(false);
|
||||
if (!manaInputCancelled) {
|
||||
game.getAction().sacrifice(offering, ability, table);
|
||||
game.getAction().sacrifice(offering, ability, table, null);
|
||||
}
|
||||
ability.resetSacrificedAsOffering();
|
||||
}
|
||||
@@ -682,7 +681,7 @@ public class HumanPlay {
|
||||
final Card emerge = ability.getSacrificedAsEmerge();
|
||||
emerge.setUsedToPay(false);
|
||||
if (!manaInputCancelled) {
|
||||
game.getAction().sacrifice(emerge, ability, table);
|
||||
game.getAction().sacrifice(emerge, ability, table, null);
|
||||
}
|
||||
ability.resetSacrificedAsEmerge();
|
||||
}
|
||||
@@ -786,7 +785,7 @@ public class HumanPlay {
|
||||
if (ability.getSacrificedAsOffering() != null) {
|
||||
System.out.println("Finishing up Offering");
|
||||
offering.setUsedToPay(false);
|
||||
activator.getGame().getAction().sacrifice(offering, ability, null);
|
||||
activator.getGame().getAction().sacrifice(offering, ability, null, null);
|
||||
ability.resetSacrificedAsOffering();
|
||||
}
|
||||
}
|
||||
@@ -797,7 +796,7 @@ public class HumanPlay {
|
||||
if (ability.getSacrificedAsEmerge() != null) {
|
||||
System.out.println("Finishing up Emerge");
|
||||
emerge.setUsedToPay(false);
|
||||
activator.getGame().getAction().sacrifice(emerge, ability, null);
|
||||
activator.getGame().getAction().sacrifice(emerge, ability, null, null);
|
||||
ability.resetSacrificedAsEmerge();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -36,6 +38,7 @@ import com.google.common.collect.Multimap;
|
||||
import forge.LobbyPlayer;
|
||||
import forge.StaticData;
|
||||
import forge.ai.GameState;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
import forge.card.CardDb;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardType;
|
||||
@@ -393,11 +396,11 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
@Override
|
||||
public Map<GameEntity, Integer> divideShield(Card effectSource, Map<GameEntity, Integer> affected, int shieldAmount) {
|
||||
final CardView vSource = CardView.get(effectSource);
|
||||
final Map<GameEntityView, Integer> vAffected = new HashMap<>(affected.size());
|
||||
final Map<Object, Integer> vAffected = new HashMap<>(affected.size());
|
||||
for (Map.Entry<GameEntity, Integer> e : affected.entrySet()) {
|
||||
vAffected.put(GameEntityView.get(e.getKey()), e.getValue());
|
||||
}
|
||||
final Map<GameEntityView, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, shieldAmount, false,
|
||||
final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, shieldAmount, false,
|
||||
localizer.getMessage("lblShield"));
|
||||
Map<GameEntity, Integer> result = new HashMap<>(vResult.size());
|
||||
for (Map.Entry<GameEntity, Integer> e : affected.entrySet()) {
|
||||
@@ -408,6 +411,28 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Byte, Integer> specifyManaCombo(SpellAbility sa, ColorSet colorSet, int manaAmount, boolean different) {
|
||||
final CardView vSource = CardView.get(sa.getHostCard());
|
||||
final Map<Object, Integer> vAffected = new LinkedHashMap<>(manaAmount);
|
||||
Integer maxAmount = different ? 1 : manaAmount;
|
||||
Iterator<Byte> it = colorSet.iterator();
|
||||
while (it.hasNext()) {
|
||||
vAffected.put(it.next(), maxAmount);
|
||||
}
|
||||
final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, manaAmount, false,
|
||||
localizer.getMessage("lblMana").toLowerCase());
|
||||
Map<Byte, Integer> result = new HashMap<>(vResult.size());
|
||||
it = colorSet.iterator();
|
||||
while (it.hasNext()) {
|
||||
Byte color = it.next();
|
||||
if (vResult.containsKey(color)) {
|
||||
result.put(color, vResult.get(color));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer announceRequirements(final SpellAbility ability, final String announce) {
|
||||
int max = Integer.MAX_VALUE;
|
||||
@@ -487,7 +512,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
|
||||
private boolean useSelectCardsInput(final FCollectionView<? extends GameEntity> sourceList) {
|
||||
// can't use InputSelect from GUI thread (e.g., DevMode Tutor)
|
||||
if ( FThreads.isGuiThread() ) { return false; }
|
||||
if (FThreads.isGuiThread()) { return false; }
|
||||
|
||||
// if UI_SELECT_FROM_CARD_DISPLAYS not set use InputSelect only for battlefield and player hand
|
||||
// if UI_SELECT_FROM_CARD_DISPLAYS set and using desktop GUI use InputSelect for any zone that can be shown
|
||||
@@ -576,8 +601,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
tempShow(delayedReveal.getCards());
|
||||
}
|
||||
|
||||
GameEntityViewMap<T, GameEntityView> gameCacheChoose = GameEntityView.getMap(optionList);
|
||||
|
||||
if (useSelectCardsInput(optionList)) {
|
||||
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, isOptional ? 0 : 1, 1,
|
||||
optionList, sa);
|
||||
@@ -588,6 +611,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
return Iterables.getFirst(input.getSelected(), null);
|
||||
}
|
||||
|
||||
GameEntityViewMap<T, GameEntityView> gameCacheChoose = GameEntityView.getMap(optionList);
|
||||
final GameEntityView result = getGui().chooseSingleEntityForEffect(title,
|
||||
gameCacheChoose.getTrackableKeys(), delayedReveal, isOptional);
|
||||
endTempShowCards();
|
||||
@@ -601,8 +625,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
@Override
|
||||
public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min, final int max,
|
||||
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer, Map<String, Object> params) {
|
||||
|
||||
|
||||
// useful details for debugging problems with the mass select logic
|
||||
Sentry.getContext().addExtra("Card", sa.getCardView().toString());
|
||||
Sentry.getContext().addExtra("SpellAbility", sa.toString());
|
||||
@@ -630,6 +652,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
endTempShowCards();
|
||||
return (List<T>) input.getSelected();
|
||||
}
|
||||
|
||||
GameEntityViewMap<T, GameEntityView> gameCacheEntity = GameEntityView.getMap(optionList);
|
||||
final List<GameEntityView> views = getGui().chooseEntitiesForEffect(title, gameCacheEntity.getTrackableKeys(), min, max, delayedReveal);
|
||||
endTempShowCards();
|
||||
@@ -675,8 +698,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
Map<SpellAbilityView, SpellAbility> spellViewCache = SpellAbilityView.getMap(spells);
|
||||
Object choice = getGui().one(title, Lists.newArrayList(spellViewCache.keySet()));
|
||||
|
||||
// Human is supposed to read the message and understand from it what to
|
||||
// choose
|
||||
// Human is supposed to read the message and understand from it what to choose
|
||||
return spellViewCache.get(choice);
|
||||
}
|
||||
|
||||
@@ -923,8 +945,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
CardCollection toTop = null;
|
||||
|
||||
tempShowCards(topN);
|
||||
if ( FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) &&
|
||||
(!GuiBase.getInterface().isLibgdxPort()) && (!GuiBase.isNetworkplay())) { //prevent crash for desktop vs mobile port it will crash the netplay since mobile doesnt have manipulatecardlist, send the alternate below
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) &&
|
||||
(!GuiBase.getInterface().isLibgdxPort()) && (!GuiBase.isNetworkplay())) { //prevent crash for desktop vs mobile port it will crash the netplay since mobile doesnt have manipulatecardlist, send the alternate below
|
||||
CardCollectionView cardList = player.getCardsIn(ZoneType.Library);
|
||||
ImmutablePair<CardCollection, CardCollection> result =
|
||||
arrangeForMove(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cardList, topN, true, true);
|
||||
@@ -1541,8 +1563,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
|
||||
@Override
|
||||
public List<SpellAbility> chooseSaToActivateFromOpeningHand(final List<SpellAbility> usableFromOpeningHand) {
|
||||
|
||||
|
||||
final CardCollection srcCards = new CardCollection();
|
||||
for (final SpellAbility sa : usableFromOpeningHand) {
|
||||
srcCards.add(sa.getHostCard());
|
||||
@@ -1950,7 +1970,44 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
checkSA = checkSA.getSubAbility();
|
||||
}
|
||||
|
||||
return select.chooseTargets(null, null, null, false, canFilterMustTarget);
|
||||
boolean result = select.chooseTargets(null, null, null, false, canFilterMustTarget);
|
||||
|
||||
// assign divided as you choose values
|
||||
if (result && currentAbility.isDividedAsYouChoose() && currentAbility.getStillToDivide() > 0) {
|
||||
int amount = currentAbility.getStillToDivide();
|
||||
final List<GameEntity> targets = currentAbility.getTargets().getTargetEntities();
|
||||
if (targets.size() == 1) {
|
||||
currentAbility.addDividedAllocation(targets.get(0), amount);
|
||||
} else if (targets.size() == amount) {
|
||||
for (GameEntity e : targets) {
|
||||
currentAbility.addDividedAllocation(e, 1);
|
||||
}
|
||||
} else if (targets.size() > amount) {
|
||||
return false;
|
||||
} else {
|
||||
String label = "lblDamage";
|
||||
if (currentAbility.getApi() == ApiType.PreventDamage) {
|
||||
label = "lblShield";
|
||||
} else if (currentAbility.getApi() == ApiType.PutCounter) {
|
||||
label = "lblCounters";
|
||||
}
|
||||
label = localizer.getMessage(label).toLowerCase();
|
||||
final CardView vSource = CardView.get(currentAbility.getHostCard());
|
||||
final Map<Object, Integer> vTargets = new HashMap<>(targets.size());
|
||||
for (GameEntity e : targets) {
|
||||
vTargets.put(GameEntityView.get(e), amount);
|
||||
}
|
||||
final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vTargets, amount, true, label);
|
||||
for (GameEntity e : targets) {
|
||||
currentAbility.addDividedAllocation(e, vResult.get(GameEntityView.get(e)));
|
||||
}
|
||||
if (currentAbility.getStillToDivide() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2431,7 +2488,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
if (subtract) {
|
||||
card.subtractCounter(counter, count);
|
||||
} else {
|
||||
card.addCounter(counter, count, card.getController(), false, null);
|
||||
card.addCounter(counter, count, card.getController(), null, false, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2495,7 +2552,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
*/
|
||||
@Override
|
||||
public void setPlayerLife() {
|
||||
|
||||
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(getGame().getPlayers());
|
||||
|
||||
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblSetLifeforWhichPlayer"), gameCachePlayer.getTrackableKeys());
|
||||
@@ -2942,6 +2998,18 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void askAI() {
|
||||
PlayerControllerAi ai = new PlayerControllerAi(player.getGame(), player, player.getOriginalLobbyPlayer());
|
||||
player.runWithController(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<SpellAbility> sas = ai.chooseSpellAbilityToPlay();
|
||||
SpellAbility chosen = sas == null ? null : sas.get(0);
|
||||
getGui().message(chosen == null ? "AI doesn't want to play anything right now" : chosen.getHostCard().toString(), "AI Play Suggestion");
|
||||
}
|
||||
}, ai);
|
||||
}
|
||||
}
|
||||
|
||||
private IMacroSystem macros;
|
||||
|
||||
@@ -73,7 +73,7 @@ public abstract class ImageFetcher {
|
||||
System.err.println("Paper card not found for: " + imageKey);
|
||||
return;
|
||||
}
|
||||
final boolean backFace = ImageUtil.hasBackFacePicture(paperCard);
|
||||
final boolean backFace = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
||||
final String filename = ImageUtil.getImageKey(paperCard, backFace, true);
|
||||
destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user