mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Use VAssignGenericAmount dialog to assign mana combo
This commit is contained in:
@@ -137,6 +137,23 @@ public class PlayerControllerAi extends PlayerController {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Byte, Integer> specifyManaCombo(SpellAbility sa, ColorSet colorSet, int manaAmount, boolean different) {
|
||||
Map<Byte, Integer> result = new HashMap<>();
|
||||
for (int i = 0; i < manaAmount; ++i) {
|
||||
Byte chosen = chooseColor("", sa, colorSet);
|
||||
if (result.containsKey(chosen)) {
|
||||
result.put(chosen, result.get(chosen) + 1);
|
||||
} else {
|
||||
result.put(chosen, 1);
|
||||
}
|
||||
if (different) {
|
||||
colorSet = ColorSet.fromMask(colorSet.getColor() - chosen);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer announceRequirements(SpellAbility ability, String announce) {
|
||||
// For now, these "announcements" are made within the AI classes of the appropriate SA effects
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.game.ability.effects;
|
||||
import static forge.util.TextUtil.toManaString;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -61,34 +62,54 @@ public class ManaEffect extends SpellAbilityEffect {
|
||||
String[] colorsNeeded = express.isEmpty() ? null : express.split(" ");
|
||||
boolean differentChoice = abMana.getOrigProduced().contains("Different");
|
||||
ColorSet fullOptions = colorOptions;
|
||||
for (int nMana = 0; nMana < amount; nMana++) {
|
||||
String choice = "";
|
||||
if (colorsNeeded != null && colorsNeeded.length > nMana) { // select from express choices if possible
|
||||
colorOptions = ColorSet
|
||||
.fromMask(fullOptions.getColor() & ManaAtom.fromName(colorsNeeded[nMana]));
|
||||
}
|
||||
if (colorOptions.isColorless() && colorsProduced.length > 0) {
|
||||
// If we just need generic mana, no reason to ask the controller for a choice,
|
||||
// just use the first possible color.
|
||||
choice = colorsProduced[differentChoice ? nMana : 0];
|
||||
} else {
|
||||
byte chosenColor = p.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa,
|
||||
differentChoice && (colorsNeeded == null || colorsNeeded.length <= nMana) ? fullOptions : colorOptions);
|
||||
if (chosenColor == 0)
|
||||
throw new RuntimeException("ManaEffect::resolve() /*combo mana*/ - " + p + " color mana choice is empty for " + card.getName());
|
||||
|
||||
if (differentChoice) {
|
||||
fullOptions = ColorSet.fromMask(fullOptions.getColor() - chosenColor);
|
||||
// Use specifyManaCombo if possible
|
||||
if (colorsNeeded == null && amount > 1) {
|
||||
Map<Byte, Integer> choices = p.getController().specifyManaCombo(sa, colorOptions, amount, differentChoice);
|
||||
for (Map.Entry<Byte, Integer> e : choices.entrySet()) {
|
||||
Byte chosenColor = e.getKey();
|
||||
String choice = MagicColor.toShortString(chosenColor);
|
||||
Integer count = e.getValue();
|
||||
while (count > 0) {
|
||||
if (choiceString.length() > 0) {
|
||||
choiceString.append(" ");
|
||||
}
|
||||
choiceString.append(choice);
|
||||
if (sa.hasParam("TwoEach")) {
|
||||
choiceString.append(" ").append(choice);
|
||||
}
|
||||
--count;
|
||||
}
|
||||
choice = MagicColor.toShortString(chosenColor);
|
||||
}
|
||||
} else {
|
||||
for (int nMana = 0; nMana < amount; nMana++) {
|
||||
String choice = "";
|
||||
if (colorsNeeded != null && colorsNeeded.length > nMana) { // select from express choices if possible
|
||||
colorOptions = ColorSet
|
||||
.fromMask(fullOptions.getColor() & ManaAtom.fromName(colorsNeeded[nMana]));
|
||||
}
|
||||
if (colorOptions.isColorless() && colorsProduced.length > 0) {
|
||||
// If we just need generic mana, no reason to ask the controller for a choice,
|
||||
// just use the first possible color.
|
||||
choice = colorsProduced[differentChoice ? nMana : 0];
|
||||
} else {
|
||||
byte chosenColor = p.getController().chooseColor(Localizer.getInstance().getMessage("lblSelectManaProduce"), sa,
|
||||
differentChoice && (colorsNeeded == null || colorsNeeded.length <= nMana) ? fullOptions : colorOptions);
|
||||
if (chosenColor == 0)
|
||||
throw new RuntimeException("ManaEffect::resolve() /*combo mana*/ - " + p + " color mana choice is empty for " + card.getName());
|
||||
|
||||
if (nMana > 0) {
|
||||
choiceString.append(" ");
|
||||
}
|
||||
choiceString.append(choice);
|
||||
if (sa.hasParam("TwoEach")) {
|
||||
choiceString.append(" ").append(choice);
|
||||
if (differentChoice) {
|
||||
fullOptions = ColorSet.fromMask(fullOptions.getColor() - chosenColor);
|
||||
}
|
||||
choice = MagicColor.toShortString(chosenColor);
|
||||
}
|
||||
|
||||
if (nMana > 0) {
|
||||
choiceString.append(" ");
|
||||
}
|
||||
choiceString.append(choice);
|
||||
if (sa.hasParam("TwoEach")) {
|
||||
choiceString.append(" ").append(choice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +149,7 @@ public class ManaEffect extends SpellAbilityEffect {
|
||||
|
||||
if (type.equals("EnchantedManaCost")) {
|
||||
Card enchanted = card.getEnchantingCard();
|
||||
if (enchanted == null )
|
||||
if (enchanted == null )
|
||||
continue;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -234,7 +255,7 @@ public class ManaEffect extends SpellAbilityEffect {
|
||||
* a {@link forge.card.spellability.AbilityMana} object.
|
||||
* @param af
|
||||
* a {@link forge.game.ability.AbilityFactory} object.
|
||||
*
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ import forge.item.PaperCard;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.collect.FCollectionView;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A prototype for player controller class
|
||||
*
|
||||
*
|
||||
* Handles phase skips for now.
|
||||
*/
|
||||
public abstract class PlayerController {
|
||||
@@ -109,21 +109,22 @@ public abstract class PlayerController {
|
||||
|
||||
public abstract Map<Card, Integer> assignCombatDamage(Card attacker, CardCollectionView blockers, int damageDealt, GameEntity defender, boolean overrideOrder);
|
||||
public abstract Map<GameEntity, Integer> divideShield(Card effectSource, Map<GameEntity, Integer> affected, int shieldAmount);
|
||||
public abstract Map<Byte, Integer> specifyManaCombo(SpellAbility sa, ColorSet colorSet, int manaAmount, boolean different);
|
||||
|
||||
public abstract Integer announceRequirements(SpellAbility ability, String announce);
|
||||
public abstract CardCollectionView choosePermanentsToSacrifice(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message);
|
||||
public abstract CardCollectionView choosePermanentsToDestroy(SpellAbility sa, int min, int max, CardCollectionView validTargets, String message);
|
||||
public abstract TargetChoices chooseNewTargetsFor(SpellAbility ability, Predicate<GameObject> filter, boolean optional);
|
||||
public abstract boolean chooseTargetsFor(SpellAbility currentAbility); // this is bad a function for it assigns targets to sa inside its body
|
||||
public abstract boolean chooseTargetsFor(SpellAbility currentAbility); // this is bad a function for it assigns targets to sa inside its body
|
||||
|
||||
// Specify a target of a spell (Spellskite)
|
||||
public abstract Pair<SpellAbilityStackInstance, GameObject> chooseTarget(SpellAbility sa, List<Pair<SpellAbilityStackInstance, GameObject>> allTargets);
|
||||
|
||||
// Q: why is there min/max and optional at once? A: This is to handle cases like 'choose 3 to 5 cards or none at all'
|
||||
// Q: why is there min/max and optional at once? A: This is to handle cases like 'choose 3 to 5 cards or none at all'
|
||||
public abstract CardCollectionView chooseCardsForEffect(CardCollectionView sourceList, SpellAbility sa, String title, int min, int max, boolean isOptional, Map<String, Object> params);
|
||||
|
||||
|
||||
public final <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, SpellAbility sa, String title, Map<String, Object> params) { return chooseSingleEntityForEffect(optionList, null, sa, title, false, null, params); }
|
||||
public final <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, SpellAbility sa, String title, boolean isOptional, Map<String, Object> params) { return chooseSingleEntityForEffect(optionList, null, sa, title, isOptional, null, params); }
|
||||
public final <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, SpellAbility sa, String title, boolean isOptional, Map<String, Object> params) { return chooseSingleEntityForEffect(optionList, null, sa, title, isOptional, null, params); }
|
||||
public abstract <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player relatedPlayer, Map<String, Object> params);
|
||||
|
||||
public abstract List<SpellAbility> chooseSpellAbilitiesForEffect(List<SpellAbility> spells, SpellAbility sa, String title, int num, Map<String, Object> params);
|
||||
@@ -209,7 +210,7 @@ public abstract class PlayerController {
|
||||
public final boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice) { return chooseBinary(sa, question, kindOfChoice, (Boolean) null); }
|
||||
public abstract boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Boolean defaultChioce);
|
||||
public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Map<String, Object> params) { return chooseBinary(sa, question, kindOfChoice); }
|
||||
|
||||
|
||||
public abstract boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call);
|
||||
public abstract Card chooseProtectionShield(GameEntity entityBeingDamaged, List<String> options, Map<String, Card> choiceMap);
|
||||
|
||||
@@ -260,7 +261,7 @@ public abstract class PlayerController {
|
||||
public abstract String chooseCardName(SpellAbility sa, Predicate<ICardFace> cpp, String valid, String message);
|
||||
|
||||
public abstract String chooseCardName(SpellAbility sa, List<ICardFace> faces, String message);
|
||||
// better to have this odd method than those if playerType comparison in ChangeZone
|
||||
// better to have this odd method than those if playerType comparison in ChangeZone
|
||||
public abstract Card chooseSingleCardForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, CardCollection fetchList, DelayedReveal delayedReveal, String selectPrompt, boolean isOptional, Player decider);
|
||||
|
||||
public abstract List<Card> chooseCardsForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, CardCollection fetchList, int min, int max, DelayedReveal delayedReveal, String selectPrompt, Player decider);
|
||||
|
||||
@@ -1029,13 +1029,13 @@ public final class CMatchUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<GameEntityView, Integer> assignGenericAmount(final CardView effectSource, final Map<GameEntityView, Integer> target,
|
||||
public Map<Object, Integer> assignGenericAmount(final CardView effectSource, final Map<Object, Integer> target,
|
||||
final int amount, final boolean atLeastOne, final String amountLabel) {
|
||||
if (amount <= 0) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final AtomicReference<Map<GameEntityView, Integer>> result = new AtomicReference<>();
|
||||
final AtomicReference<Map<Object, Integer>> result = new AtomicReference<>();
|
||||
FThreads.invokeInEdtAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -34,10 +34,11 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.Border;
|
||||
|
||||
import forge.game.GameEntityView;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.gui.SOverlayUtils;
|
||||
import forge.localinstance.skin.FSkinProp;
|
||||
import forge.toolbox.FButton;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FScrollPane;
|
||||
@@ -52,11 +53,7 @@ import forge.view.arcane.MiscCardPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
/**
|
||||
* Assembles Swing components of assign damage dialog.
|
||||
*
|
||||
* This needs a JDialog to maintain a modal state.
|
||||
* Without the modal state, the PhaseHandler automatically
|
||||
* moves forward to phase Main2 without assigning damage.
|
||||
* Assembles Swing components of assign generic amount dialog.
|
||||
*
|
||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||
*/
|
||||
@@ -80,12 +77,12 @@ public class VAssignGenericAmount {
|
||||
private final FButton btnReset = new FButton(localizer.getMessage("lblReset"));
|
||||
|
||||
private static class AssignTarget {
|
||||
public final GameEntityView entity;
|
||||
public final Object entity;
|
||||
public final JLabel label;
|
||||
public final int max;
|
||||
public int amount;
|
||||
|
||||
public AssignTarget(final GameEntityView e, final JLabel lbl, int max0) {
|
||||
public AssignTarget(final Object e, final JLabel lbl, int max0) {
|
||||
entity = e;
|
||||
label = lbl;
|
||||
max = max0;
|
||||
@@ -122,7 +119,7 @@ public class VAssignGenericAmount {
|
||||
}
|
||||
};
|
||||
|
||||
public VAssignGenericAmount(final CMatchUI matchUI, final CardView effectSource, final Map<GameEntityView, Integer> targets, final int amount, final boolean atLeastOne, final String amountLabel) {
|
||||
public VAssignGenericAmount(final CMatchUI matchUI, final CardView effectSource, final Map<Object, Integer> targets, final int amount, final boolean atLeastOne, final String amountLabel) {
|
||||
this.matchUI = matchUI;
|
||||
dlg.setTitle(localizer.getMessage("lbLAssignAmountForEffect", amountLabel, effectSource.toString()));
|
||||
|
||||
@@ -158,7 +155,7 @@ public class VAssignGenericAmount {
|
||||
final FScrollPane scrTargets = new FScrollPane(pnlTargets, false);
|
||||
|
||||
// Top row of cards...
|
||||
for (final Map.Entry<GameEntityView, Integer> e : targets.entrySet()) {
|
||||
for (final Map.Entry<Object, Integer> e : targets.entrySet()) {
|
||||
int maxAmount = e.getValue() != null ? e.getValue() : amount;
|
||||
final AssignTarget at = new AssignTarget(e.getKey(), new FLabel.Builder().text("0").fontSize(18).fontAlign(SwingConstants.CENTER).build(), maxAmount);
|
||||
addPanelForTarget(pnlTargets, at);
|
||||
@@ -166,7 +163,11 @@ public class VAssignGenericAmount {
|
||||
|
||||
// ... bottom row of labels.
|
||||
for (final AssignTarget l : targetsList) {
|
||||
pnlTargets.add(l.label, "w 145px!, h 30px!, gap 5px 5px 0 5px");
|
||||
if (l.entity instanceof Byte) {
|
||||
pnlTargets.add(l.label, "w 100px!, h 30px!, gap 5px 5px 0 5px");
|
||||
} else {
|
||||
pnlTargets.add(l.label, "w 145px!, h 30px!, gap 5px 5px 0 5px");
|
||||
}
|
||||
}
|
||||
|
||||
btnOK.addActionListener(new ActionListener() {
|
||||
@@ -217,6 +218,27 @@ public class VAssignGenericAmount {
|
||||
pnlTargets.add(mp, "w 145px!, h 170px!, gap 5px 5px 3px 3px, ax center");
|
||||
mp.addMouseListener(mad);
|
||||
targetsMap.put(mp, at);
|
||||
} else if (at.entity instanceof Byte) {
|
||||
SkinImage manaSymbol;
|
||||
Byte color = (Byte) at.entity;
|
||||
if (color == MagicColor.WHITE) {
|
||||
manaSymbol = FSkin.getImage(FSkinProp.IMG_MANA_W);
|
||||
} else if (color == MagicColor.BLUE) {
|
||||
manaSymbol = FSkin.getImage(FSkinProp.IMG_MANA_U);
|
||||
} else if (color == MagicColor.BLACK) {
|
||||
manaSymbol = FSkin.getImage(FSkinProp.IMG_MANA_B);
|
||||
} else if (color == MagicColor.RED) {
|
||||
manaSymbol = FSkin.getImage(FSkinProp.IMG_MANA_R);
|
||||
} else if (color == MagicColor.GREEN) {
|
||||
manaSymbol = FSkin.getImage(FSkinProp.IMG_MANA_G);
|
||||
} else { // Should never come here, but add this to avoid compile error
|
||||
manaSymbol = FSkin.getImage(FSkinProp.IMG_MANA_COLORLESS);
|
||||
}
|
||||
final MiscCardPanel mp = new MiscCardPanel(matchUI, "", manaSymbol);
|
||||
mp.setCardBounds(0, 0, 70, 70);
|
||||
pnlTargets.add(mp, "w 100px!, h 150px!, gap 5px 5px 3px 3px, ax center");
|
||||
mp.addMouseListener(mad);
|
||||
targetsMap.put(mp, at);
|
||||
}
|
||||
targetsList.add(at);
|
||||
}
|
||||
@@ -313,8 +335,8 @@ public class VAssignGenericAmount {
|
||||
SOverlayUtils.hideOverlay();
|
||||
}
|
||||
|
||||
public Map<GameEntityView, Integer> getAssignedMap() {
|
||||
Map<GameEntityView, Integer> result = new HashMap<>(targetsList.size());
|
||||
public Map<Object, Integer> getAssignedMap() {
|
||||
Map<Object, Integer> result = new HashMap<>(targetsList.size());
|
||||
for (AssignTarget at : targetsList)
|
||||
result.put(at.entity, at.amount);
|
||||
return result;
|
||||
|
||||
@@ -80,7 +80,7 @@ import forge.util.collect.FCollectionView;
|
||||
/**
|
||||
* Default harmless implementation for tests.
|
||||
* Test-specific behaviour can easily be added by mocking (parts of) this class.
|
||||
*
|
||||
*
|
||||
* Note that the current PlayerController implementations seem to be responsible for handling some game logic,
|
||||
* and even aside from that, they are theoretically capable of making illegal choices (which are then not blocked by the real game logic).
|
||||
* Test cases that need to override the default behaviour of this class should make sure to do so in a way that does not invalidate their correctness.
|
||||
@@ -151,6 +151,10 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
throw new IllegalStateException("Erring on the side of caution here...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Byte, Integer> specifyManaCombo(SpellAbility sa, ColorSet colorSet, int manaAmount, boolean different) {
|
||||
throw new IllegalStateException("Erring on the side of caution here...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer announceRequirements(SpellAbility ability, String announce) {
|
||||
@@ -422,7 +426,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
@Override
|
||||
public List<SpellAbility> chooseSpellAbilityToPlay() {
|
||||
//TODO: This method has to return the spellability chosen by player
|
||||
// It should not play the sa right from here. The code has been left as it is to quickly adapt to changed playercontroller interface
|
||||
// It should not play the sa right from here. The code has been left as it is to quickly adapt to changed playercontroller interface
|
||||
if (playerActions != null) {
|
||||
CastSpellFromHandAction castSpellFromHand = playerActions.getNextActionIfApplicable(player, getGame(), CastSpellFromHandAction.class);
|
||||
if (castSpellFromHand != null) {
|
||||
@@ -476,7 +480,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
public byte chooseColor(String message, SpellAbility sa, ColorSet colors) {
|
||||
return Iterables.getFirst(colors, MagicColor.WHITE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte chooseColorAllowColorless(String message, Card card, ColorSet colors) {
|
||||
return Iterables.getFirst(colors, (byte)0);
|
||||
@@ -551,7 +555,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
ComputerUtil.playStack(sa, player, getGame());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void prepareSingleSa(final Card host, final SpellAbility sa, boolean isMandatory){
|
||||
if (sa.hasParam("TargetingPlayer")) {
|
||||
Player targetingPlayer = AbilityUtils.getDefinedPlayers(host, sa.getParam("TargetingPlayer"), sa).get(0);
|
||||
@@ -583,7 +587,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
} else {
|
||||
ComputerUtil.playStack(tgtSA, player, getGame());
|
||||
}
|
||||
} else
|
||||
} else
|
||||
return false; // didn't play spell
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -397,9 +397,9 @@ public class MatchController extends AbstractGuiGame {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<GameEntityView, Integer> assignGenericAmount(final CardView effectSource, final Map<GameEntityView, Integer> targets,
|
||||
public Map<Object, Integer> assignGenericAmount(final CardView effectSource, final Map<Object, Integer> targets,
|
||||
final int amount, final boolean atLeastOne, final String amountLabel) {
|
||||
return new WaitCallback<Map<GameEntityView, Integer>>() {
|
||||
return new WaitCallback<Map<Object, Integer>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
final VAssignGenericAmount v = new VAssignGenericAmount(effectSource, targets, amount, atLeastOne, amountLabel, this);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
* Copyright (C) 2021 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,7 +32,7 @@ import forge.assets.FSkinColor.Colors;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.card.CardZoom;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.screens.match.MatchController;
|
||||
@@ -56,7 +56,7 @@ public class VAssignGenericAmount extends FDialog {
|
||||
private static final float CARD_GAP_X = Utils.scale(10);
|
||||
private static final float ADD_BTN_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
|
||||
|
||||
private final Callback<Map<GameEntityView, Integer>> callback;
|
||||
private final Callback<Map<Object, Integer>> callback;
|
||||
private final int totalAmountToAssign;
|
||||
|
||||
private final String lblAmount;
|
||||
@@ -67,7 +67,7 @@ public class VAssignGenericAmount extends FDialog {
|
||||
private final TargetsPanel pnlTargets;
|
||||
|
||||
private final List<AssignTarget> targetsList = new ArrayList<>();
|
||||
private final Map<GameEntityView, AssignTarget> targetsMap = new HashMap<>();
|
||||
private final Map<Object, AssignTarget> targetsMap = new HashMap<>();
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
@@ -76,7 +76,7 @@ public class VAssignGenericAmount extends FDialog {
|
||||
* @param amount Total amount to be assigned
|
||||
* @param atLeastOne Must assign at least one amount to each target
|
||||
*/
|
||||
public VAssignGenericAmount(final CardView effectSource, final Map<GameEntityView, Integer> targets, final int amount, final boolean atLeastOne, final String amountLabel, final WaitCallback<Map<GameEntityView, Integer>> waitCallback) {
|
||||
public VAssignGenericAmount(final CardView effectSource, final Map<Object, Integer> targets, final int amount, final boolean atLeastOne, final String amountLabel, final WaitCallback<Map<Object, Integer>> waitCallback) {
|
||||
super(Localizer.getInstance().getMessage("lbLAssignAmountForEffect", amountLabel, CardTranslation.getTranslatedName(effectSource.getName())) , 2);
|
||||
|
||||
callback = waitCallback;
|
||||
@@ -132,13 +132,13 @@ public class VAssignGenericAmount extends FDialog {
|
||||
}
|
||||
|
||||
private class TargetsPanel extends FScrollPane {
|
||||
private TargetsPanel(final Map<GameEntityView, Integer> targets) {
|
||||
for (final Map.Entry<GameEntityView, Integer> e : targets.entrySet()) {
|
||||
private TargetsPanel(final Map<Object, Integer> targets) {
|
||||
for (final Map.Entry<Object, Integer> e : targets.entrySet()) {
|
||||
addDamageTarget(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void addDamageTarget(GameEntityView entity, int max) {
|
||||
private void addDamageTarget(Object entity, int max) {
|
||||
AssignTarget at = add(new AssignTarget(entity, max));
|
||||
targetsMap.put(entity, at);
|
||||
targetsList.add(at);
|
||||
@@ -164,23 +164,38 @@ public class VAssignGenericAmount extends FDialog {
|
||||
}
|
||||
|
||||
private class AssignTarget extends FContainer {
|
||||
private final GameEntityView entity;
|
||||
private final Object entity;
|
||||
private final FDisplayObject obj;
|
||||
private final FLabel label, btnSubtract, btnAdd;
|
||||
private final int max;
|
||||
private int amount;
|
||||
|
||||
public AssignTarget(GameEntityView entity0, int max0) {
|
||||
public AssignTarget(Object entity0, int max0) {
|
||||
entity = entity0;
|
||||
max = max0;
|
||||
if (entity instanceof CardView) {
|
||||
obj = add(new EffectSourcePanel((CardView)entity));
|
||||
}
|
||||
else if (entity instanceof PlayerView) {
|
||||
} else if (entity instanceof PlayerView) {
|
||||
PlayerView player = (PlayerView)entity;
|
||||
obj = add(new MiscTargetPanel(player.getName(), MatchController.getPlayerAvatar(player)));
|
||||
}
|
||||
else {
|
||||
} else if (entity instanceof Byte) {
|
||||
FSkinImage manaSymbol;
|
||||
Byte color = (Byte) entity;
|
||||
if (color == MagicColor.WHITE) {
|
||||
manaSymbol = FSkinImage.MANA_W;
|
||||
} else if (color == MagicColor.BLUE) {
|
||||
manaSymbol = FSkinImage.MANA_U;
|
||||
} else if (color == MagicColor.BLACK) {
|
||||
manaSymbol = FSkinImage.MANA_B;
|
||||
} else if (color == MagicColor.RED) {
|
||||
manaSymbol = FSkinImage.MANA_R;
|
||||
} else if (color == MagicColor.GREEN) {
|
||||
manaSymbol = FSkinImage.MANA_G;
|
||||
} else { // Should never come here, but add this to avoid compile error
|
||||
manaSymbol = FSkinImage.MANA_COLORLESS;
|
||||
}
|
||||
obj = add(new MiscTargetPanel("", manaSymbol));
|
||||
} else {
|
||||
obj = add(new MiscTargetPanel(entity.toString(), FSkinImage.UNKNOWN));
|
||||
}
|
||||
label = add(new FLabel.Builder().text("0").font(FSkinFont.get(18)).align(Align.center).build());
|
||||
@@ -256,7 +271,7 @@ public class VAssignGenericAmount extends FDialog {
|
||||
}
|
||||
}
|
||||
|
||||
private void assignAmountTo(GameEntityView source, boolean isAdding) {
|
||||
private void assignAmountTo(Object source, boolean isAdding) {
|
||||
AssignTarget at = targetsMap.get(source);
|
||||
int assigned = at.amount;
|
||||
int leftToAssign = Math.max(0, at.max - assigned);
|
||||
@@ -344,8 +359,8 @@ public class VAssignGenericAmount extends FDialog {
|
||||
callback.run(getAssignedMap());
|
||||
}
|
||||
|
||||
public Map<GameEntityView, Integer> getAssignedMap() {
|
||||
Map<GameEntityView, Integer> result = new HashMap<>(targetsList.size());
|
||||
public Map<Object, Integer> getAssignedMap() {
|
||||
Map<Object, Integer> result = new HashMap<>(targetsList.size());
|
||||
for (AssignTarget at : targetsList)
|
||||
result.put(at.entity, at.amount);
|
||||
return result;
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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;
|
||||
@@ -394,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()) {
|
||||
@@ -409,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;
|
||||
@@ -1974,11 +1998,11 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
}
|
||||
label = localizer.getMessage(label).toLowerCase();
|
||||
final CardView vSource = CardView.get(currentAbility.getHostCard());
|
||||
final Map<GameEntityView, Integer> vTargets = new HashMap<>(targets.size());
|
||||
final Map<Object, Integer> vTargets = new HashMap<>(targets.size());
|
||||
for (GameEntity e : targets) {
|
||||
vTargets.put(GameEntityView.get(e), amount);
|
||||
}
|
||||
final Map<GameEntityView, Integer> vResult = getGui().assignGenericAmount(vSource, vTargets, amount, true, label);
|
||||
final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vTargets, amount, true, label);
|
||||
for (GameEntity e : targets) {
|
||||
currentAbility.addDividedAllocation(e, vResult.get(GameEntityView.get(e)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user