mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
InputSelectTargets moved to separate class,
SpellAbilityRequirements - all options are passed as parameters to fillRequirements
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -13847,6 +13847,7 @@ src/main/java/forge/control/input/InputSelectCards.java -text
|
|||||||
src/main/java/forge/control/input/InputSelectCardsFromList.java -text
|
src/main/java/forge/control/input/InputSelectCardsFromList.java -text
|
||||||
src/main/java/forge/control/input/InputSelectMany.java -text
|
src/main/java/forge/control/input/InputSelectMany.java -text
|
||||||
src/main/java/forge/control/input/InputSelectManyBase.java -text
|
src/main/java/forge/control/input/InputSelectManyBase.java -text
|
||||||
|
src/main/java/forge/control/input/InputSelectTargets.java -text
|
||||||
src/main/java/forge/control/input/InputSynchronized.java -text
|
src/main/java/forge/control/input/InputSynchronized.java -text
|
||||||
src/main/java/forge/control/input/InputSyncronizedBase.java -text
|
src/main/java/forge/control/input/InputSyncronizedBase.java -text
|
||||||
src/main/java/forge/control/input/package-info.java svneol=native#text/plain
|
src/main/java/forge/control/input/package-info.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -39,24 +39,15 @@ import forge.game.zone.Zone;
|
|||||||
*/
|
*/
|
||||||
public class SpellAbilityRequirements {
|
public class SpellAbilityRequirements {
|
||||||
private final SpellAbility ability;
|
private final SpellAbility ability;
|
||||||
private final TargetChooser select;
|
|
||||||
private final CostPayment payment;
|
private final CostPayment payment;
|
||||||
private boolean isFree;
|
|
||||||
private boolean skipStack = false;
|
|
||||||
private boolean isAlreadyTargeted = false;
|
|
||||||
|
|
||||||
public void setAlreadyTargeted() { isAlreadyTargeted = true; }
|
|
||||||
public final void setSkipStack() { this.skipStack = true; }
|
|
||||||
public void setFree() { this.isFree = true; }
|
|
||||||
|
|
||||||
public SpellAbilityRequirements(final SpellAbility sa, final CostPayment cp) {
|
public SpellAbilityRequirements(final SpellAbility sa, final CostPayment cp) {
|
||||||
this.ability = sa;
|
this.ability = sa;
|
||||||
this.select = new TargetChooser(sa);
|
|
||||||
this.payment = cp;
|
this.payment = cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final void fillRequirements() {
|
public final void fillRequirements(boolean isAlreadyTargeted, boolean isFree, boolean skipStack) {
|
||||||
final GameState game = Singletons.getModel().getGame();
|
final GameState game = Singletons.getModel().getGame();
|
||||||
|
|
||||||
// used to rollback
|
// used to rollback
|
||||||
@@ -75,26 +66,26 @@ public class SpellAbilityRequirements {
|
|||||||
|
|
||||||
// Announce things like how many times you want to Multikick or the value of X
|
// Announce things like how many times you want to Multikick or the value of X
|
||||||
if (!this.announceRequirements()) {
|
if (!this.announceRequirements()) {
|
||||||
this.select.setCancel(true);
|
rollbackAbility(fromZone, zonePosition, null);
|
||||||
rollbackAbility(fromZone, zonePosition);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final TargetChooser select = new TargetChooser(ability);
|
||||||
// Skip to paying if parent ability doesn't target and has no
|
// Skip to paying if parent ability doesn't target and has no
|
||||||
// subAbilities.
|
// subAbilities.
|
||||||
// (or trigger case where its already targeted)
|
// (or trigger case where its already targeted)
|
||||||
boolean acceptsTargets = this.select.doesTarget() || this.ability.getSubAbility() != null;
|
boolean acceptsTargets = select.doesTarget() || this.ability.getSubAbility() != null;
|
||||||
if (!isAlreadyTargeted && acceptsTargets) {
|
if (!isAlreadyTargeted && acceptsTargets) {
|
||||||
this.select.clearTargets();
|
select.clearTargets();
|
||||||
this.select.chooseTargets();
|
select.chooseTargets();
|
||||||
if (this.select.isCanceled()) {
|
if (select.isCanceled()) {
|
||||||
rollbackAbility(fromZone, zonePosition);
|
rollbackAbility(fromZone, zonePosition, select);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Payment
|
// Payment
|
||||||
boolean paymentMade = this.isFree;
|
boolean paymentMade = isFree;
|
||||||
|
|
||||||
if (!paymentMade) {
|
if (!paymentMade) {
|
||||||
this.payment.changeCost();
|
this.payment.changeCost();
|
||||||
@@ -102,12 +93,12 @@ public class SpellAbilityRequirements {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!paymentMade) {
|
if (!paymentMade) {
|
||||||
rollbackAbility(fromZone, zonePosition);
|
rollbackAbility(fromZone, zonePosition, select);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.isFree || this.payment.isFullyPaid()) {
|
else if (isFree || this.payment.isFullyPaid()) {
|
||||||
if (this.skipStack) {
|
if (skipStack) {
|
||||||
AbilityUtils.resolve(this.ability, false);
|
AbilityUtils.resolve(this.ability, false);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -116,13 +107,13 @@ public class SpellAbilityRequirements {
|
|||||||
game.getStack().addAndUnfreeze(this.ability);
|
game.getStack().addAndUnfreeze(this.ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warning about this - resolution may come in another thread, and it would still need its targets
|
// no worries here. The same thread must resolve, and by this moment ability will have been resolved already
|
||||||
this.select.clearTargets();
|
select.clearTargets();
|
||||||
game.getAction().checkStateEffects();
|
game.getAction().checkStateEffects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rollbackAbility(Zone fromZone, int zonePosition) {
|
private void rollbackAbility(Zone fromZone, int zonePosition, TargetChooser select) {
|
||||||
// cancel ability during target choosing
|
// cancel ability during target choosing
|
||||||
final Card c = this.ability.getSourceCard();
|
final Card c = this.ability.getSourceCard();
|
||||||
|
|
||||||
@@ -136,8 +127,8 @@ public class SpellAbilityRequirements {
|
|||||||
Singletons.getModel().getGame().getAction().moveTo(fromZone, c, zonePosition >= 0 ? Integer.valueOf(zonePosition) : null);
|
Singletons.getModel().getGame().getAction().moveTo(fromZone, c, zonePosition >= 0 ? Integer.valueOf(zonePosition) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.select != null) {
|
if (select != null) {
|
||||||
this.select.clearTargets();
|
select.clearTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ability.resetOnceResolved();
|
this.ability.resetOnceResolved();
|
||||||
@@ -147,7 +138,7 @@ public class SpellAbilityRequirements {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean announceRequirements() {
|
private boolean announceRequirements() {
|
||||||
// Announcing Requirements like Choosing X or Multikicker
|
// Announcing Requirements like Choosing X or Multikicker
|
||||||
// SA Params as comma delimited list
|
// SA Params as comma delimited list
|
||||||
String announce = ability.getParam("Announce");
|
String announce = ability.getParam("Announce");
|
||||||
|
|||||||
@@ -20,24 +20,19 @@ package forge.card.spellability;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CardLists;
|
import forge.CardLists;
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.GameEntity;
|
|
||||||
import forge.card.ability.AbilityUtils;
|
import forge.card.ability.AbilityUtils;
|
||||||
import forge.card.ability.ApiType;
|
import forge.control.input.InputSelectTargets;
|
||||||
import forge.control.input.InputSyncronizedBase;
|
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.view.ButtonUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -48,249 +43,18 @@ import forge.view.ButtonUtil;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class TargetChooser {
|
public class TargetChooser {
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for this type.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static final class InputSelectTargets extends InputSyncronizedBase {
|
|
||||||
private final List<Card> choices;
|
|
||||||
// some cards can be targeted several times (eg: distribute damage as you choose)
|
|
||||||
private final Map<GameEntity, Integer> targetDepth = new HashMap<GameEntity, Integer>();
|
|
||||||
private final Target tgt;
|
|
||||||
private final SpellAbility sa;
|
|
||||||
private boolean bCancel = false;
|
|
||||||
private boolean bOk = false;
|
|
||||||
private final boolean mandatory;
|
|
||||||
private static final long serialVersionUID = -1091595663541356356L;
|
|
||||||
|
|
||||||
public final boolean hasCancelled() { return bCancel; }
|
|
||||||
public final boolean hasPressedOk() { return bOk; }
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for Constructor.
|
|
||||||
* @param select
|
|
||||||
* @param choices
|
|
||||||
* @param req
|
|
||||||
* @param alreadyTargeted
|
|
||||||
* @param targeted
|
|
||||||
* @param tgt
|
|
||||||
* @param sa
|
|
||||||
* @param mandatory
|
|
||||||
*/
|
|
||||||
public InputSelectTargets(List<Card> choices, SpellAbility sa, boolean mandatory) {
|
|
||||||
super(sa.getActivatingPlayer());
|
|
||||||
this.choices = choices;
|
|
||||||
this.tgt = sa.getTarget();
|
|
||||||
this.sa = sa;
|
|
||||||
this.mandatory = mandatory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("Targeted:\n");
|
|
||||||
for (final Entry<GameEntity, Integer> o : targetDepth.entrySet()) {
|
|
||||||
sb.append(o.getKey());
|
|
||||||
if( o.getValue() > 1 )
|
|
||||||
sb.append(" (").append(o.getValue()).append(" times)");
|
|
||||||
sb.append("\n");
|
|
||||||
}
|
|
||||||
//sb.append(tgt.getTargetedString()).append("\n");
|
|
||||||
sb.append(tgt.getVTSelection());
|
|
||||||
|
|
||||||
showMessage(sb.toString());
|
|
||||||
|
|
||||||
// If reached Minimum targets, enable OK button
|
|
||||||
if (!tgt.isMinTargetsChosen(sa.getSourceCard(), sa) || tgt.isDividedAsYouChoose()) {
|
|
||||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
|
||||||
// Player has to click on a target
|
|
||||||
ButtonUtil.disableAll();
|
|
||||||
} else {
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
|
||||||
// Player has to click on a target or ok
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
} else {
|
|
||||||
ButtonUtil.enableAllFocusOk();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonCancel() {
|
|
||||||
bCancel = true;
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonOK() {
|
|
||||||
bOk = true;
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectCard(final Card card) {
|
|
||||||
if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// leave this in temporarily, there some seriously wrong things going on here
|
|
||||||
if (!card.canBeTargetedBy(sa)) {
|
|
||||||
showMessage("Cannot target this card (Shroud? Protection? Restrictions?).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!choices.contains(card)) {
|
|
||||||
showMessage("This card is not a valid choice for some other reason besides (Shroud? Protection? Restrictions?).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tgt.isDividedAsYouChoose()) {
|
|
||||||
final int stillToDivide = tgt.getStillToDivide();
|
|
||||||
int allocatedPortion = 0;
|
|
||||||
// allow allocation only if the max targets isn't reached and there are more candidates
|
|
||||||
if ((tgt.getNumTargeted() + 1 < tgt.getMaxTargets(sa.getSourceCard(), sa))
|
|
||||||
&& (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
|
||||||
final Integer[] choices = new Integer[stillToDivide];
|
|
||||||
for (int i = 1; i <= stillToDivide; i++) {
|
|
||||||
choices[i - 1] = 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 ";
|
|
||||||
} else if (sa.getApi() == ApiType.PutCounter) {
|
|
||||||
apiBasedMessage = "Select how many counters to distribute to ";
|
|
||||||
}
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(apiBasedMessage);
|
|
||||||
sb.append(card.toString());
|
|
||||||
Integer chosen = GuiChoose.oneOrNone(sb.toString(), choices);
|
|
||||||
if (null == chosen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
allocatedPortion = chosen;
|
|
||||||
} else { // otherwise assign the rest of the damage/protection
|
|
||||||
allocatedPortion = stillToDivide;
|
|
||||||
}
|
|
||||||
tgt.setStillToDivide(stillToDivide - allocatedPortion);
|
|
||||||
tgt.addDividedAllocation(card, allocatedPortion);
|
|
||||||
}
|
|
||||||
addTarget(card);
|
|
||||||
} // selectCard()
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectPlayer(final Player player) {
|
|
||||||
if (!tgt.isUniqueTargets() && targetDepth.containsKey(player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sa.canTarget(player)) {
|
|
||||||
showMessage("Cannot target this player (Hexproof? Protection? Restrictions?).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tgt.isDividedAsYouChoose()) {
|
|
||||||
final int stillToDivide = tgt.getStillToDivide();
|
|
||||||
int allocatedPortion = 0;
|
|
||||||
// allow allocation only if the max targets isn't reached and there are more candidates
|
|
||||||
if ((tgt.getNumTargeted() + 1 < tgt.getMaxTargets(sa.getSourceCard(), sa)) && (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
|
||||||
final Integer[] choices = new Integer[stillToDivide];
|
|
||||||
for (int i = 1; i <= stillToDivide; i++) {
|
|
||||||
choices[i - 1] = 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(player.getName());
|
|
||||||
Integer chosen = GuiChoose.oneOrNone(sb.toString(), choices);
|
|
||||||
if (null == chosen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
allocatedPortion = chosen;
|
|
||||||
} else { // otherwise assign the rest of the damage/protection
|
|
||||||
allocatedPortion = stillToDivide;
|
|
||||||
}
|
|
||||||
tgt.setStillToDivide(stillToDivide - allocatedPortion);
|
|
||||||
tgt.addDividedAllocation(player, allocatedPortion);
|
|
||||||
}
|
|
||||||
addTarget(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTarget(GameEntity ge) {
|
|
||||||
tgt.addTarget(ge);
|
|
||||||
Integer val = targetDepth.get(ge);
|
|
||||||
targetDepth.put(ge, val == null ? Integer.valueOf(1) : Integer.valueOf(val.intValue() + 1) );
|
|
||||||
|
|
||||||
if(hasAllTargets()) {
|
|
||||||
bOk = true;
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void done() {
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasAllTargets() {
|
|
||||||
return tgt.isMaxTargetsChosen(sa.getSourceCard(), sa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final SpellAbility ability;
|
private final SpellAbility ability;
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Constructor for Target_Selection.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param tgt
|
|
||||||
* a {@link forge.card.spellability.Target} object.
|
|
||||||
* @param sa
|
|
||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
public TargetChooser(final SpellAbility sa) {
|
public TargetChooser(final SpellAbility sa) {
|
||||||
this.ability = sa;
|
this.ability = sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private final Target getTgt() {
|
||||||
* <p>
|
|
||||||
* getTgt.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a {@link forge.card.spellability.Target} object.
|
|
||||||
*/
|
|
||||||
public final Target getTgt() {
|
|
||||||
return this.ability.getTarget();
|
return this.ability.getTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private final Card getCard() {
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>ability</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
public final SpellAbility getAbility() {
|
|
||||||
return this.ability;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>card</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a {@link forge.Card} object.
|
|
||||||
*/
|
|
||||||
public final Card getCard() {
|
|
||||||
return this.ability.getSourceCard();
|
return this.ability.getSourceCard();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +106,7 @@ public class TargetChooser {
|
|||||||
|
|
||||||
public final boolean chooseTargets() {
|
public final boolean chooseTargets() {
|
||||||
Target tgt = getTgt();
|
Target tgt = getTgt();
|
||||||
final boolean canTarget = tgt == null ? false : tgt.doesTarget();
|
final boolean canTarget = doesTarget();
|
||||||
final int minTargets = canTarget ? tgt.getMinTargets(getCard(), ability) : 0;
|
final int minTargets = canTarget ? tgt.getMinTargets(getCard(), ability) : 0;
|
||||||
final int maxTargets = canTarget ? tgt.getMaxTargets(getCard(), ability) : 0;
|
final int maxTargets = canTarget ? tgt.getMaxTargets(getCard(), ability) : 0;
|
||||||
final int numTargeted = canTarget ? tgt.getNumTargeted() : 0;
|
final int numTargeted = canTarget ? tgt.getNumTargeted() : 0;
|
||||||
|
|||||||
212
src/main/java/forge/control/input/InputSelectTargets.java
Normal file
212
src/main/java/forge/control/input/InputSelectTargets.java
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
package forge.control.input;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.GameEntity;
|
||||||
|
import forge.card.ability.ApiType;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.gui.GuiChoose;
|
||||||
|
import forge.view.ButtonUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for this type.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class InputSelectTargets extends InputSyncronizedBase {
|
||||||
|
private final List<Card> choices;
|
||||||
|
// some cards can be targeted several times (eg: distribute damage as you choose)
|
||||||
|
private final Map<GameEntity, Integer> targetDepth = new HashMap<GameEntity, Integer>();
|
||||||
|
private final Target tgt;
|
||||||
|
private final SpellAbility sa;
|
||||||
|
private boolean bCancel = false;
|
||||||
|
private boolean bOk = false;
|
||||||
|
private final boolean mandatory;
|
||||||
|
private static final long serialVersionUID = -1091595663541356356L;
|
||||||
|
|
||||||
|
public final boolean hasCancelled() { return bCancel; }
|
||||||
|
public final boolean hasPressedOk() { return bOk; }
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for Constructor.
|
||||||
|
* @param select
|
||||||
|
* @param choices
|
||||||
|
* @param req
|
||||||
|
* @param alreadyTargeted
|
||||||
|
* @param targeted
|
||||||
|
* @param tgt
|
||||||
|
* @param sa
|
||||||
|
* @param mandatory
|
||||||
|
*/
|
||||||
|
public InputSelectTargets(List<Card> choices, SpellAbility sa, boolean mandatory) {
|
||||||
|
super(sa.getActivatingPlayer());
|
||||||
|
this.choices = choices;
|
||||||
|
this.tgt = sa.getTarget();
|
||||||
|
this.sa = sa;
|
||||||
|
this.mandatory = mandatory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showMessage() {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Targeted:\n");
|
||||||
|
for (final Entry<GameEntity, Integer> o : targetDepth.entrySet()) {
|
||||||
|
sb.append(o.getKey());
|
||||||
|
if( o.getValue() > 1 )
|
||||||
|
sb.append(" (").append(o.getValue()).append(" times)");
|
||||||
|
sb.append("\n");
|
||||||
|
}
|
||||||
|
//sb.append(tgt.getTargetedString()).append("\n");
|
||||||
|
sb.append(tgt.getVTSelection());
|
||||||
|
|
||||||
|
showMessage(sb.toString());
|
||||||
|
|
||||||
|
// If reached Minimum targets, enable OK button
|
||||||
|
if (!tgt.isMinTargetsChosen(sa.getSourceCard(), sa) || tgt.isDividedAsYouChoose()) {
|
||||||
|
if (mandatory && tgt.hasCandidates(sa, true)) {
|
||||||
|
// Player has to click on a target
|
||||||
|
ButtonUtil.disableAll();
|
||||||
|
} else {
|
||||||
|
ButtonUtil.enableOnlyCancel();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mandatory && tgt.hasCandidates(sa, true)) {
|
||||||
|
// Player has to click on a target or ok
|
||||||
|
ButtonUtil.enableOnlyOk();
|
||||||
|
} else {
|
||||||
|
ButtonUtil.enableAllFocusOk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
bCancel = true;
|
||||||
|
this.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonOK() {
|
||||||
|
bOk = true;
|
||||||
|
this.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectCard(final Card card) {
|
||||||
|
if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// leave this in temporarily, there some seriously wrong things going on here
|
||||||
|
if (!card.canBeTargetedBy(sa)) {
|
||||||
|
showMessage("Cannot target this card (Shroud? Protection? Restrictions?).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!choices.contains(card)) {
|
||||||
|
showMessage("This card is not a valid choice for some other reason besides (Shroud? Protection? Restrictions?).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgt.isDividedAsYouChoose()) {
|
||||||
|
final int stillToDivide = tgt.getStillToDivide();
|
||||||
|
int allocatedPortion = 0;
|
||||||
|
// allow allocation only if the max targets isn't reached and there are more candidates
|
||||||
|
if ((tgt.getNumTargeted() + 1 < tgt.getMaxTargets(sa.getSourceCard(), sa))
|
||||||
|
&& (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
||||||
|
final Integer[] choices = new Integer[stillToDivide];
|
||||||
|
for (int i = 1; i <= stillToDivide; i++) {
|
||||||
|
choices[i - 1] = 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 ";
|
||||||
|
} else if (sa.getApi() == ApiType.PutCounter) {
|
||||||
|
apiBasedMessage = "Select how many counters to distribute to ";
|
||||||
|
}
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(apiBasedMessage);
|
||||||
|
sb.append(card.toString());
|
||||||
|
Integer chosen = GuiChoose.oneOrNone(sb.toString(), choices);
|
||||||
|
if (null == chosen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allocatedPortion = chosen;
|
||||||
|
} else { // otherwise assign the rest of the damage/protection
|
||||||
|
allocatedPortion = stillToDivide;
|
||||||
|
}
|
||||||
|
tgt.setStillToDivide(stillToDivide - allocatedPortion);
|
||||||
|
tgt.addDividedAllocation(card, allocatedPortion);
|
||||||
|
}
|
||||||
|
addTarget(card);
|
||||||
|
} // selectCard()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectPlayer(final Player player) {
|
||||||
|
if (!tgt.isUniqueTargets() && targetDepth.containsKey(player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sa.canTarget(player)) {
|
||||||
|
showMessage("Cannot target this player (Hexproof? Protection? Restrictions?).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgt.isDividedAsYouChoose()) {
|
||||||
|
final int stillToDivide = tgt.getStillToDivide();
|
||||||
|
int allocatedPortion = 0;
|
||||||
|
// allow allocation only if the max targets isn't reached and there are more candidates
|
||||||
|
if ((tgt.getNumTargeted() + 1 < tgt.getMaxTargets(sa.getSourceCard(), sa)) && (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
||||||
|
final Integer[] choices = new Integer[stillToDivide];
|
||||||
|
for (int i = 1; i <= stillToDivide; i++) {
|
||||||
|
choices[i - 1] = 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(player.getName());
|
||||||
|
Integer chosen = GuiChoose.oneOrNone(sb.toString(), choices);
|
||||||
|
if (null == chosen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allocatedPortion = chosen;
|
||||||
|
} else { // otherwise assign the rest of the damage/protection
|
||||||
|
allocatedPortion = stillToDivide;
|
||||||
|
}
|
||||||
|
tgt.setStillToDivide(stillToDivide - allocatedPortion);
|
||||||
|
tgt.addDividedAllocation(player, allocatedPortion);
|
||||||
|
}
|
||||||
|
addTarget(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addTarget(GameEntity ge) {
|
||||||
|
tgt.addTarget(ge);
|
||||||
|
Integer val = targetDepth.get(ge);
|
||||||
|
targetDepth.put(ge, val == null ? Integer.valueOf(1) : Integer.valueOf(val.intValue() + 1) );
|
||||||
|
|
||||||
|
if(hasAllTargets()) {
|
||||||
|
bOk = true;
|
||||||
|
this.done();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this.showMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void done() {
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasAllTargets() {
|
||||||
|
return tgt.isMaxTargetsChosen(sa.getSourceCard(), sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,7 +66,9 @@ public class GameActionPlay {
|
|||||||
public final void playSpellAbilityWithoutPayingManaCost(final SpellAbility sa) {
|
public final void playSpellAbilityWithoutPayingManaCost(final SpellAbility sa) {
|
||||||
FThreads.checkEDT("GameActionPlay.playSpellAbilityWithoutPayingManaCost", false);
|
FThreads.checkEDT("GameActionPlay.playSpellAbilityWithoutPayingManaCost", false);
|
||||||
final Card source = sa.getSourceCard();
|
final Card source = sa.getSourceCard();
|
||||||
setSplitCardState(source, sa); // Split card support
|
|
||||||
|
if( source.isSplitCard())
|
||||||
|
setSplitCardState(source, sa);
|
||||||
|
|
||||||
if (sa.getPayCosts() != null) {
|
if (sa.getPayCosts() != null) {
|
||||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||||
@@ -75,8 +77,7 @@ public class GameActionPlay {
|
|||||||
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa);
|
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa);
|
||||||
|
|
||||||
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
||||||
req.setFree();
|
req.fillRequirements(false, true, false);
|
||||||
req.fillRequirements();
|
|
||||||
} else {
|
} else {
|
||||||
if (sa.isSpell()) {
|
if (sa.isSpell()) {
|
||||||
final Card c = sa.getSourceCard();
|
final Card c = sa.getSourceCard();
|
||||||
@@ -356,7 +357,7 @@ public class GameActionPlay {
|
|||||||
|
|
||||||
final Card source = sa.getSourceCard();
|
final Card source = sa.getSourceCard();
|
||||||
|
|
||||||
// Split card support
|
if(source.isSplitCard())
|
||||||
setSplitCardState(source, sa);
|
setSplitCardState(source, sa);
|
||||||
|
|
||||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||||
@@ -389,7 +390,7 @@ public class GameActionPlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
||||||
req.fillRequirements();
|
req.fillRequirements(false, false, false);
|
||||||
} else {
|
} else {
|
||||||
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost());
|
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost());
|
||||||
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
||||||
@@ -437,10 +438,8 @@ public class GameActionPlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
||||||
if( useOldTargets )
|
|
||||||
req.setAlreadyTargeted();
|
req.fillRequirements(useOldTargets, false, true);
|
||||||
req.setSkipStack();
|
|
||||||
req.fillRequirements();
|
|
||||||
} else {
|
} else {
|
||||||
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost());
|
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost());
|
||||||
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
||||||
@@ -492,21 +491,20 @@ public class GameActionPlay {
|
|||||||
|
|
||||||
private void setSplitCardState(final Card source, SpellAbility sa) {
|
private void setSplitCardState(final Card source, SpellAbility sa) {
|
||||||
// Split card support
|
// Split card support
|
||||||
if (source.isSplitCard()) {
|
|
||||||
List<SpellAbility> leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility();
|
List<SpellAbility> leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility();
|
||||||
List<SpellAbility> rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility();
|
List<SpellAbility> rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility();
|
||||||
for (SpellAbility a : leftSplitAbilities) {
|
for (SpellAbility a : leftSplitAbilities) {
|
||||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||||
source.setState(CardCharacteristicName.LeftSplit);
|
source.setState(CardCharacteristicName.LeftSplit);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (SpellAbility a : rightSplitAbilities) {
|
for (SpellAbility a : rightSplitAbilities) {
|
||||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||||
source.setState(CardCharacteristicName.RightSplit);
|
source.setState(CardCharacteristicName.RightSplit);
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user