mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- Added code support for cards dependent on the maximum total CMC of targets (e.g. March from the Tomb). Basic AI support also added (but can most likely be made smarter, feel free to improve).
- Note that the relevant SA parameter has been renamed to "MaxTotalTargetCMC" (from "WithTotalCMC") to avoid confusion with the ChangeZone parameter "WithTotalCMC" that means "the total CMC of a single card".
This commit is contained in:
@@ -1021,6 +1021,14 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
// if max CMC exceeded, stop choosing
|
||||
if (sa.hasParam("MaxTotalTargetCMC")) {
|
||||
if (choice.getCMC() > sa.getTargetRestrictions().getMaxTotalCMC(choice, sa) - sa.getTargets().getTotalTargetedCMC()) {
|
||||
list.remove(choice);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
list.remove(choice);
|
||||
sa.getTargets().add(choice);
|
||||
}
|
||||
|
||||
@@ -230,6 +230,11 @@ public final class AbilityFactory {
|
||||
abTgt.setZone(ZoneType.listValueOf(mapParams.get("TgtZone")));
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("MaxTotalTargetCMC")) {
|
||||
// only target cards up to a certain total max CMC
|
||||
abTgt.setMaxTotalCMC(mapParams.get("MaxTotalTargetCMC"));
|
||||
}
|
||||
|
||||
// TargetValidTargeting most for Counter: e.g. target spell that
|
||||
// targets X.
|
||||
if (mapParams.containsKey("TargetValidTargeting")) {
|
||||
|
||||
@@ -464,6 +464,24 @@ public final class CardUtil {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove cards exceeding total CMC
|
||||
if (ability.hasParam("MaxTotalTargetCMC")) {
|
||||
int totalCMCTargeted = 0;
|
||||
for (final Card c : targeted) {
|
||||
totalCMCTargeted += c.getCMC();
|
||||
}
|
||||
|
||||
final List<Card> choicesCopy = Lists.newArrayList(choices);
|
||||
for (final Card c : choicesCopy) {
|
||||
if (c.getCMC() > tgt.getMaxTotalCMC(c, ability)) {
|
||||
choices.remove(c);
|
||||
}
|
||||
if (c.getCMC() > tgt.getMaxTotalCMC(c, ability) - totalCMCTargeted) {
|
||||
choices.remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If all cards (including subability targets) must have the same controller
|
||||
if (tgt.isSameController() && !targetedObjects.isEmpty()) {
|
||||
final List<Card> list = new ArrayList<Card>();
|
||||
|
||||
@@ -48,6 +48,14 @@ public class TargetChoices implements Cloneable {
|
||||
return numTargeted;
|
||||
}
|
||||
|
||||
public final int getTotalTargetedCMC() {
|
||||
int totalCMC = 0;
|
||||
for (Card c : targetCards) {
|
||||
totalCMC += c.getCMC();
|
||||
}
|
||||
return totalCMC;
|
||||
}
|
||||
|
||||
public final boolean add(final GameObject o) {
|
||||
if (o instanceof Player) {
|
||||
return addTarget((Player) o);
|
||||
|
||||
@@ -70,6 +70,9 @@ public class TargetRestrictions {
|
||||
private String minTargets;
|
||||
private String maxTargets;
|
||||
|
||||
// What's the max CMC of targeted?
|
||||
private String maxTotalCMC;
|
||||
|
||||
// For "Divided" cards. Is this better in TargetChoices?
|
||||
private boolean dividedAsYouChoose = false;
|
||||
private HashMap<Object, Integer> dividedMap = new HashMap<Object, Integer>();
|
||||
@@ -93,6 +96,7 @@ public class TargetRestrictions {
|
||||
this.validTgts = this.originalValidTgts.clone();
|
||||
this.minTargets = target.getMinTargets();
|
||||
this.maxTargets = target.getMaxTargets();
|
||||
this.maxTotalCMC = target.getMaxTotalCMC();
|
||||
this.tgtZone = target.getZone();
|
||||
this.saValidTargeting = target.getSAValidTargeting();
|
||||
this.dividedAsYouChoose = target.isDividedAsYouChoose();
|
||||
@@ -153,6 +157,18 @@ public class TargetRestrictions {
|
||||
this.bMandatory = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* setMaxTotalCMC.
|
||||
* </p>
|
||||
*
|
||||
* @param cmc
|
||||
* a String.
|
||||
*/
|
||||
public final void setMaxTotalCMC(final String cmc) {
|
||||
this.maxTotalCMC = cmc;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doesTarget.
|
||||
@@ -204,6 +220,19 @@ public class TargetRestrictions {
|
||||
return this.maxTargets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the max targets.
|
||||
*
|
||||
* @return the max targets
|
||||
*/
|
||||
private final String getMaxTotalCMC() {
|
||||
return this.maxTotalCMC;
|
||||
}
|
||||
|
||||
public final int getMaxTotalCMC(final Card c, final SpellAbility sa) {
|
||||
return AbilityUtils.calculateAmount(c, this.maxTotalCMC, sa);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>minTargets</code>.
|
||||
|
||||
@@ -71,6 +71,7 @@ public class TargetSelection {
|
||||
// Number of targets is explicitly set only if spell is being redirected (ex. Swerve or Redirect)
|
||||
final int minTargets = numTargets != null ? numTargets.intValue() : tgt.getMinTargets(ability.getHostCard(), ability);
|
||||
final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getHostCard(), ability);
|
||||
final int maxTotalCMC = tgt.getMaxTotalCMC(ability.getHostCard(), ability);
|
||||
final int numTargeted = ability.getTargets().getNumTargeted();
|
||||
|
||||
final boolean hasEnoughTargets = minTargets == 0 || numTargeted >= minTargets;
|
||||
|
||||
Reference in New Issue
Block a user