mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Use current shard when trying to pay with combo mana (#3130)
* Use current shard when trying to pay with combo mana
This commit is contained in:
@@ -1507,7 +1507,7 @@ public class AiAttackController {
|
||||
}
|
||||
if (sa.usesTargeting()) {
|
||||
sa.setActivatingPlayer(c.getController(), true);
|
||||
List<Card> validTargets = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
||||
List<Card> validTargets = CardUtil.getValidCardsToTarget(sa);
|
||||
if (validTargets.isEmpty()) {
|
||||
missTarget = true;
|
||||
break;
|
||||
|
||||
@@ -644,7 +644,6 @@ public class AiController {
|
||||
public SpellAbility predictSpellToCastInMain2(ApiType exceptSA) {
|
||||
return predictSpellToCastInMain2(exceptSA, true);
|
||||
}
|
||||
|
||||
private SpellAbility predictSpellToCastInMain2(ApiType exceptSA, boolean handOnly) {
|
||||
if (!getBooleanProperty(AiProps.PREDICT_SPELLS_FOR_MAIN2)) {
|
||||
return null;
|
||||
@@ -684,15 +683,12 @@ public class AiController {
|
||||
public boolean reserveManaSourcesForNextSpell(SpellAbility sa, SpellAbility exceptForSa) {
|
||||
return reserveManaSources(sa, null, false, true, exceptForSa);
|
||||
}
|
||||
|
||||
public boolean reserveManaSources(SpellAbility sa) {
|
||||
return reserveManaSources(sa, PhaseType.MAIN2, false, false, null);
|
||||
}
|
||||
|
||||
public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) {
|
||||
return reserveManaSources(sa, phaseType, enemy, true, null);
|
||||
}
|
||||
|
||||
public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy, boolean forNextSpell, SpellAbility exceptForThisSa) {
|
||||
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, true, 0);
|
||||
CardCollection manaSources = ComputerUtilMana.getManaSourcesToPayCost(cost, sa, player);
|
||||
|
||||
@@ -868,7 +868,7 @@ public class ComputerUtilCost {
|
||||
if (sa.usesTargeting()) {
|
||||
// if announce is used as min targets, check what the max possible number would be
|
||||
if ("X".equals(sa.getTargetRestrictions().getMinTargets())) {
|
||||
val = ObjectUtils.min(val, CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa).size());
|
||||
val = ObjectUtils.min(val, CardUtil.getValidCardsToTarget(sa).size());
|
||||
}
|
||||
|
||||
if (sa.hasParam("AIMaxTgtsCount")) {
|
||||
|
||||
@@ -962,6 +962,7 @@ public class ComputerUtilMana {
|
||||
ManaCostShard toPay, SpellAbility saPayment) {
|
||||
AbilityManaPart m = saPayment.getManaPart();
|
||||
if (m.isComboMana()) {
|
||||
m.setExpressChoice(ColorSet.fromMask(toPay.getColorMask()));
|
||||
getComboManaChoice(ai, saPayment, sa, cost);
|
||||
}
|
||||
else if (saPayment.getApi() == ApiType.ManaReflected) {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class SpecialAiLogic {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Card> targetable = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
||||
List<Card> targetable = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
CardCollection listOpp = CardLists.filterControlledBy(targetable, ai.getOpponents());
|
||||
if (isDestroy) {
|
||||
|
||||
@@ -228,7 +228,7 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
} else if (sa.usesTargeting() && mandatory) {
|
||||
// fallback if animate is mandatory
|
||||
sa.resetTargets();
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -123,8 +123,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Chained to the Rocks")) {
|
||||
final SpellAbility effectExile = AbilityFactory.getAbility(source.getSVar("TrigExile"), source);
|
||||
effectExile.setActivatingPlayer(ai, true);
|
||||
final TargetRestrictions exile_tgt = effectExile.getTargetRestrictions();
|
||||
final List<Card> targets = CardUtil.getValidCardsToTarget(exile_tgt, effectExile);
|
||||
final List<Card> targets = CardUtil.getValidCardsToTarget(effectExile);
|
||||
return !targets.isEmpty();
|
||||
}
|
||||
|
||||
@@ -1328,11 +1327,9 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return null;
|
||||
}
|
||||
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
|
||||
// Is a SA that moves target attachment
|
||||
if ("MoveTgtAura".equals(sa.getParam("AILogic"))) {
|
||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(tgt, sa), Predicates.or(CardPredicates.isControlledByAnyOf(aiPlayer.getOpponents()), new Predicate<Card>() {
|
||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(sa), Predicates.or(CardPredicates.isControlledByAnyOf(aiPlayer.getOpponents()), new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card card) {
|
||||
return ComputerUtilCard.isUselessCreature(aiPlayer, card.getAttachedTo());
|
||||
@@ -1341,7 +1338,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
|
||||
return !list.isEmpty() ? ComputerUtilCard.getBestAI(list) : null;
|
||||
} else if ("Unenchanted".equals(sa.getParam("AILogic"))) {
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
CardCollection preferred = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card card) {
|
||||
@@ -1358,10 +1355,10 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
List<Card> list = null;
|
||||
if (tgt == null) {
|
||||
list = AbilityUtils.getDefinedCards(attachSource, sa.getParam("Defined"), sa);
|
||||
if (sa.usesTargeting()) {
|
||||
list = CardUtil.getValidCardsToTarget(sa);
|
||||
} else {
|
||||
list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
list = AbilityUtils.getDefinedCards(attachSource, sa.getParam("Defined"), sa);
|
||||
}
|
||||
|
||||
if (list.isEmpty()) {
|
||||
|
||||
@@ -1432,7 +1432,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
|
||||
@@ -130,7 +130,7 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
if (sa.usesTargeting()) {
|
||||
sa.resetTargets();
|
||||
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
//Nothing to target
|
||||
if (list.isEmpty()) {
|
||||
|
||||
@@ -195,7 +195,7 @@ public class DebuffAi extends SpellAbilityAi {
|
||||
*/
|
||||
private boolean debuffMandatoryTarget(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
||||
sa.resetTargets();
|
||||
|
||||
@@ -215,7 +215,7 @@ public class EffectAi extends SpellAbilityAi {
|
||||
} else if (logic.equals("Fight")) {
|
||||
return FightAi.canFightAi(ai, sa, 0, 0);
|
||||
} else if (logic.equals("Pump")) {
|
||||
List<Card> options = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
||||
List<Card> options = CardUtil.getValidCardsToTarget(sa);
|
||||
options = CardLists.filterControlledBy(options, ai);
|
||||
if (sa.getPayCosts().hasTapCost()) {
|
||||
options.remove(sa.getHostCard());
|
||||
|
||||
@@ -213,11 +213,10 @@ public class PlayAi extends SpellAbilityAi {
|
||||
|
||||
private static List<Card> getPlayableCards(SpellAbility sa, Player ai) {
|
||||
List<Card> cards = null;
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
if (tgt != null) {
|
||||
cards = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
if (sa.usesTargeting()) {
|
||||
cards = CardUtil.getValidCardsToTarget(sa);
|
||||
} else if (!sa.hasParam("Valid")) {
|
||||
cards = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ public class ProtectAi extends SpellAbilityAi {
|
||||
private static boolean protectMandatoryTarget(final Player ai, final SpellAbility sa) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getHostCard();
|
||||
final List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
final List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
if (list.size() < tgt.getMinTargets(source, sa)) {
|
||||
sa.resetTargets();
|
||||
|
||||
@@ -617,7 +617,7 @@ public class PumpAi extends PumpAiBase {
|
||||
|
||||
private boolean pumpMandatoryTarget(final Player ai, final SpellAbility sa) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
||||
sa.resetTargets();
|
||||
|
||||
@@ -23,7 +23,6 @@ import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class SetStateAi extends SpellAbilityAi {
|
||||
@@ -79,11 +78,10 @@ public class SetStateAi extends SpellAbilityAi {
|
||||
}
|
||||
return shouldTransformCard(source, ai, ph) || "Always".equals(logic);
|
||||
} else {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
sa.resetTargets();
|
||||
|
||||
// select only the ones that can transform
|
||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(tgt, sa), CardPredicates.Presets.CREATURES, new Predicate<Card>() {
|
||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(sa), CardPredicates.Presets.CREATURES, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(Card c) {
|
||||
return c.canTransform(sa);
|
||||
@@ -106,17 +104,10 @@ public class SetStateAi extends SpellAbilityAi {
|
||||
return sa.isMinTargetChosen();
|
||||
}
|
||||
} else if ("TurnFace".equals(mode)) {
|
||||
if (!sa.usesTargeting()) {
|
||||
CardCollection list = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return shouldTurnFace(list.get(0), ai, ph) || "Always".equals(logic);
|
||||
} else {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
if (sa.usesTargeting()) {
|
||||
sa.resetTargets();
|
||||
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
||||
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
@@ -132,6 +123,12 @@ public class SetStateAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
return sa.isTargetNumberValid();
|
||||
} else {
|
||||
CardCollection list = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return shouldTurnFace(list.get(0), ai, ph) || "Always".equals(logic);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -544,7 +544,8 @@ public final class CardUtil {
|
||||
// parameters for target selection.
|
||||
// however, due to the changes necessary for SA_Requirements this is much
|
||||
// different than the original
|
||||
public static List<Card> getValidCardsToTarget(TargetRestrictions tgt, SpellAbility ability) {
|
||||
public static List<Card> getValidCardsToTarget(final SpellAbility ability) {
|
||||
final TargetRestrictions tgt = ability.getTargetRestrictions();
|
||||
final Card activatingCard = ability.getHostCard();
|
||||
final Game game = ability.getActivatingPlayer().getGame();
|
||||
final List<ZoneType> zone = tgt.getZone();
|
||||
|
||||
@@ -460,7 +460,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
if (ability.usesTargeting()) {
|
||||
// if announce is used as min targets, check what the max possible number would be
|
||||
if (announce.equals(ability.getTargetRestrictions().getMinTargets())) {
|
||||
max = Math.min(max, CardUtil.getValidCardsToTarget(ability.getTargetRestrictions(), ability).size());
|
||||
max = Math.min(max, CardUtil.getValidCardsToTarget(ability).size());
|
||||
}
|
||||
}
|
||||
if (min > max) {
|
||||
|
||||
@@ -140,7 +140,7 @@ public class TargetSelection {
|
||||
return ability.getTargets().addAll(choices);
|
||||
}
|
||||
|
||||
List<Card> validTargets = CardUtil.getValidCardsToTarget(tgt, ability);
|
||||
List<Card> validTargets = CardUtil.getValidCardsToTarget(ability);
|
||||
boolean mustTargetFiltered = false;
|
||||
if (canFilterMustTarget) {
|
||||
mustTargetFiltered = StaticAbilityMustTarget.filterMustTargetCards(controller.getPlayer(), validTargets, ability);
|
||||
|
||||
Reference in New Issue
Block a user