mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
InputSelectTargets moved to separate class,
SpellAbilityRequirements - all options are passed as parameters to fillRequirements
This commit is contained in:
@@ -39,24 +39,15 @@ import forge.game.zone.Zone;
|
||||
*/
|
||||
public class SpellAbilityRequirements {
|
||||
private final SpellAbility ability;
|
||||
private final TargetChooser select;
|
||||
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) {
|
||||
this.ability = sa;
|
||||
this.select = new TargetChooser(sa);
|
||||
this.payment = cp;
|
||||
}
|
||||
|
||||
|
||||
public final void fillRequirements() {
|
||||
public final void fillRequirements(boolean isAlreadyTargeted, boolean isFree, boolean skipStack) {
|
||||
final GameState game = Singletons.getModel().getGame();
|
||||
|
||||
// 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
|
||||
if (!this.announceRequirements()) {
|
||||
this.select.setCancel(true);
|
||||
rollbackAbility(fromZone, zonePosition);
|
||||
rollbackAbility(fromZone, zonePosition, null);
|
||||
return;
|
||||
}
|
||||
|
||||
final TargetChooser select = new TargetChooser(ability);
|
||||
// Skip to paying if parent ability doesn't target and has no
|
||||
// subAbilities.
|
||||
// (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) {
|
||||
this.select.clearTargets();
|
||||
this.select.chooseTargets();
|
||||
if (this.select.isCanceled()) {
|
||||
rollbackAbility(fromZone, zonePosition);
|
||||
select.clearTargets();
|
||||
select.chooseTargets();
|
||||
if (select.isCanceled()) {
|
||||
rollbackAbility(fromZone, zonePosition, select);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Payment
|
||||
boolean paymentMade = this.isFree;
|
||||
boolean paymentMade = isFree;
|
||||
|
||||
if (!paymentMade) {
|
||||
this.payment.changeCost();
|
||||
@@ -102,12 +93,12 @@ public class SpellAbilityRequirements {
|
||||
}
|
||||
|
||||
if (!paymentMade) {
|
||||
rollbackAbility(fromZone, zonePosition);
|
||||
rollbackAbility(fromZone, zonePosition, select);
|
||||
return;
|
||||
}
|
||||
|
||||
else if (this.isFree || this.payment.isFullyPaid()) {
|
||||
if (this.skipStack) {
|
||||
else if (isFree || this.payment.isFullyPaid()) {
|
||||
if (skipStack) {
|
||||
AbilityUtils.resolve(this.ability, false);
|
||||
} else {
|
||||
|
||||
@@ -116,13 +107,13 @@ public class SpellAbilityRequirements {
|
||||
game.getStack().addAndUnfreeze(this.ability);
|
||||
}
|
||||
|
||||
// Warning about this - resolution may come in another thread, and it would still need its targets
|
||||
this.select.clearTargets();
|
||||
// no worries here. The same thread must resolve, and by this moment ability will have been resolved already
|
||||
select.clearTargets();
|
||||
game.getAction().checkStateEffects();
|
||||
}
|
||||
}
|
||||
|
||||
private void rollbackAbility(Zone fromZone, int zonePosition) {
|
||||
private void rollbackAbility(Zone fromZone, int zonePosition, TargetChooser select) {
|
||||
// cancel ability during target choosing
|
||||
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);
|
||||
}
|
||||
|
||||
if (this.select != null) {
|
||||
this.select.clearTargets();
|
||||
if (select != null) {
|
||||
select.clearTargets();
|
||||
}
|
||||
|
||||
this.ability.resetOnceResolved();
|
||||
@@ -147,7 +138,7 @@ public class SpellAbilityRequirements {
|
||||
}
|
||||
|
||||
|
||||
public boolean announceRequirements() {
|
||||
private boolean announceRequirements() {
|
||||
// Announcing Requirements like Choosing X or Multikicker
|
||||
// SA Params as comma delimited list
|
||||
String announce = ability.getParam("Announce");
|
||||
|
||||
@@ -20,24 +20,19 @@ package forge.card.spellability;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.FThreads;
|
||||
import forge.GameEntity;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.control.input.InputSyncronizedBase;
|
||||
import forge.control.input.InputSelectTargets;
|
||||
import forge.game.GameState;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -48,249 +43,18 @@ import forge.view.ButtonUtil;
|
||||
* @version $Id$
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* <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) {
|
||||
this.ability = sa;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getTgt.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.Target} object.
|
||||
*/
|
||||
public final Target getTgt() {
|
||||
private final Target getTgt() {
|
||||
return this.ability.getTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* <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() {
|
||||
private final Card getCard() {
|
||||
return this.ability.getSourceCard();
|
||||
}
|
||||
|
||||
@@ -342,7 +106,7 @@ public class TargetChooser {
|
||||
|
||||
public final boolean chooseTargets() {
|
||||
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 maxTargets = canTarget ? tgt.getMaxTargets(getCard(), ability) : 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) {
|
||||
FThreads.checkEDT("GameActionPlay.playSpellAbilityWithoutPayingManaCost", false);
|
||||
final Card source = sa.getSourceCard();
|
||||
setSplitCardState(source, sa); // Split card support
|
||||
|
||||
if( source.isSplitCard())
|
||||
setSplitCardState(source, sa);
|
||||
|
||||
if (sa.getPayCosts() != null) {
|
||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||
@@ -75,8 +77,7 @@ public class GameActionPlay {
|
||||
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa);
|
||||
|
||||
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
||||
req.setFree();
|
||||
req.fillRequirements();
|
||||
req.fillRequirements(false, true, false);
|
||||
} else {
|
||||
if (sa.isSpell()) {
|
||||
final Card c = sa.getSourceCard();
|
||||
@@ -356,8 +357,8 @@ public class GameActionPlay {
|
||||
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
// Split card support
|
||||
setSplitCardState(source, sa);
|
||||
if(source.isSplitCard())
|
||||
setSplitCardState(source, sa);
|
||||
|
||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||
CharmEffect.makeChoices(sa);
|
||||
@@ -389,7 +390,7 @@ public class GameActionPlay {
|
||||
}
|
||||
|
||||
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
||||
req.fillRequirements();
|
||||
req.fillRequirements(false, false, false);
|
||||
} else {
|
||||
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost());
|
||||
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
||||
@@ -437,10 +438,8 @@ public class GameActionPlay {
|
||||
}
|
||||
|
||||
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, payment);
|
||||
if( useOldTargets )
|
||||
req.setAlreadyTargeted();
|
||||
req.setSkipStack();
|
||||
req.fillRequirements();
|
||||
|
||||
req.fillRequirements(useOldTargets, false, true);
|
||||
} else {
|
||||
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost());
|
||||
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
||||
@@ -492,21 +491,20 @@ public class GameActionPlay {
|
||||
|
||||
private void setSplitCardState(final Card source, SpellAbility sa) {
|
||||
// Split card support
|
||||
if (source.isSplitCard()) {
|
||||
List<SpellAbility> leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility();
|
||||
List<SpellAbility> rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility();
|
||||
for (SpellAbility a : leftSplitAbilities) {
|
||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||
source.setState(CardCharacteristicName.LeftSplit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (SpellAbility a : rightSplitAbilities) {
|
||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||
source.setState(CardCharacteristicName.RightSplit);
|
||||
break;
|
||||
}
|
||||
List<SpellAbility> leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility();
|
||||
List<SpellAbility> rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility();
|
||||
for (SpellAbility a : leftSplitAbilities) {
|
||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||
source.setState(CardCharacteristicName.LeftSplit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (SpellAbility a : rightSplitAbilities) {
|
||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
||||
source.setState(CardCharacteristicName.RightSplit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + source);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user