Card property targeted player

This commit is contained in:
Hans Mackowiak
2021-05-15 15:27:15 +00:00
committed by Michael Kamensky
parent cad42948cd
commit ff7f81c307
27 changed files with 1959 additions and 2109 deletions

View File

@@ -47,6 +47,7 @@ import forge.game.Game;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GlobalRuleChange; import forge.game.GlobalRuleChange;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.ability.SpellApiBased; import forge.game.ability.SpellApiBased;
@@ -79,6 +80,7 @@ import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode; import forge.game.player.PlayerActionConfirmMode;
import forge.game.replacement.ReplaceMoved; import forge.game.replacement.ReplaceMoved;
import forge.game.replacement.ReplacementEffect; import forge.game.replacement.ReplacementEffect;
import forge.game.replacement.ReplacementLayer;
import forge.game.replacement.ReplacementType; import forge.game.replacement.ReplacementType;
import forge.game.spellability.AbilitySub; import forge.game.spellability.AbilitySub;
import forge.game.spellability.LandAbility; import forge.game.spellability.LandAbility;
@@ -509,20 +511,35 @@ public class AiController {
//try to skip lands that enter the battlefield tapped //try to skip lands that enter the battlefield tapped
if (!nonLandsInHand.isEmpty()) { if (!nonLandsInHand.isEmpty()) {
CardCollection nonTappeddLands = new CardCollection(); CardCollection nonTappedLands = new CardCollection();
for (Card land : landList) { for (Card land : landList) {
// Is this the best way to check if a land ETB Tapped? // check replacement effects if land would enter tapped or not
if (land.hasSVar("ETBTappedSVar")) { final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(land);
repParams.put(AbilityKey.Origin, land.getZone().getZoneType());
repParams.put(AbilityKey.Destination, ZoneType.Battlefield);
repParams.put(AbilityKey.Source, land);
boolean foundTapped = false;
for (ReplacementEffect re : player.getGame().getReplacementHandler().getReplacementList(ReplacementType.Moved, repParams, ReplacementLayer.Other)) {
SpellAbility reSA = re.ensureAbility();
if (reSA == null || !ApiType.Tap.equals(reSA.getApi())) {
continue;
}
reSA.setActivatingPlayer(reSA.getHostCard().getController());
if (reSA.metConditions()) {
foundTapped = true;
break;
}
}
if (foundTapped) {
continue; continue;
} }
// Glacial Fortress and friends
if (land.hasSVar("ETBCheckSVar") && CardFactoryUtil.xCount(land, land.getSVar("ETBCheckSVar")) == 0) { nonTappedLands.add(land);
continue;
}
nonTappeddLands.add(land);
} }
if (!nonTappeddLands.isEmpty()) { if (!nonTappedLands.isEmpty()) {
landList = nonTappeddLands; landList = nonTappedLands;
} }
} }
@@ -1779,7 +1796,7 @@ public class AiController {
compareTo = Integer.parseInt(strCmpTo); compareTo = Integer.parseInt(strCmpTo);
} catch (final Exception ignored) { } catch (final Exception ignored) {
if (sa == null) { if (sa == null) {
compareTo = CardFactoryUtil.xCount(hostCard, hostCard.getSVar(strCmpTo)); compareTo = AbilityUtils.calculateAmount(hostCard, hostCard.getSVar(strCmpTo), effect);
} else { } else {
compareTo = AbilityUtils.calculateAmount(hostCard, hostCard.getSVar(strCmpTo), sa); compareTo = AbilityUtils.calculateAmount(hostCard, hostCard.getSVar(strCmpTo), sa);
} }
@@ -1789,7 +1806,7 @@ public class AiController {
int left = 0; int left = 0;
if (sa == null) { if (sa == null) {
left = CardFactoryUtil.xCount(hostCard, hostCard.getSVar(svarToCheck)); left = AbilityUtils.calculateAmount(hostCard, svarToCheck, effect);
} else { } else {
left = AbilityUtils.calculateAmount(hostCard, svarToCheck, sa); left = AbilityUtils.calculateAmount(hostCard, svarToCheck, sa);
} }

View File

@@ -1125,7 +1125,7 @@ public class ComputerUtil {
creatures2.add(creatures.get(i)); creatures2.add(creatures.get(i));
} }
} }
if (((creatures2.size() + CardUtil.getThisTurnCast("Creature.YouCtrl", vengevines.get(0)).size()) > 1) if (((creatures2.size() + CardUtil.getThisTurnCast("Creature.YouCtrl", vengevines.get(0), null).size()) > 1)
&& card.isCreature() && card.getManaCost().getCMC() <= 3) { && card.isCreature() && card.getManaCost().getCMC() <= 3) {
return true; return true;
} }

View File

@@ -982,7 +982,7 @@ public class ComputerUtilCard {
for(byte c : MagicColor.WUBRG) { for(byte c : MagicColor.WUBRG) {
String devotionCode = "Count$Devotion." + MagicColor.toLongString(c); String devotionCode = "Count$Devotion." + MagicColor.toLongString(c);
int devotion = CardFactoryUtil.xCount(sa.getHostCard(), devotionCode); int devotion = AbilityUtils.calculateAmount(sa.getHostCard(), devotionCode, sa);
if (devotion > curDevotion && !CardLists.filter(hand, CardPredicates.isColor(c)).isEmpty()) { if (devotion > curDevotion && !CardLists.filter(hand, CardPredicates.isColor(c)).isEmpty()) {
curDevotion = devotion; curDevotion = devotion;
chosenColor = MagicColor.toLongString(c); chosenColor = MagicColor.toLongString(c);
@@ -1679,37 +1679,27 @@ public class ComputerUtilCard {
// remove old boost that might be copied // remove old boost that might be copied
for (final StaticAbility stAb : c.getStaticAbilities()) { for (final StaticAbility stAb : c.getStaticAbilities()) {
vCard.removePTBoost(c.getTimestamp(), stAb.getId()); vCard.removePTBoost(c.getTimestamp(), stAb.getId());
final Map<String, String> params = stAb.getMapParams(); if (!stAb.getParam("Mode").equals("Continuous")) {
if (!params.get("Mode").equals("Continuous")) {
continue; continue;
} }
if (!params.containsKey("Affected")) { if (!stAb.hasParam("Affected")) {
continue; continue;
} }
if (!params.containsKey("AddPower") && !params.containsKey("AddToughness")) { if (!stAb.hasParam("AddPower") && !stAb.hasParam("AddToughness")) {
continue; continue;
} }
final String valid = params.get("Affected"); if (!vCard.isValid(stAb.getParam("Affected").split(","), c.getController(), c, stAb)) {
if (!vCard.isValid(valid, c.getController(), c, null)) {
continue; continue;
} }
int att = 0; int att = 0;
if (params.containsKey("AddPower")) { if (stAb.hasParam("AddPower")) {
String addP = params.get("AddPower"); String addP = stAb.getParam("AddPower");
if (addP.equals("AffectedX")) { att = AbilityUtils.calculateAmount(addP.startsWith("Affected") ? vCard : c, addP, stAb, true);
att = CardFactoryUtil.xCount(vCard, AbilityUtils.getSVar(stAb, addP));
} else {
att = AbilityUtils.calculateAmount(c, addP, stAb);
}
} }
int def = 0; int def = 0;
if (params.containsKey("AddToughness")) { if (stAb.hasParam("AddToughness")) {
String addT = params.get("AddToughness"); String addT = stAb.getParam("AddToughness");
if (addT.equals("AffectedY")) { def = AbilityUtils.calculateAmount(addT.startsWith("Affected") ? vCard : c, addT, stAb, true);
def = CardFactoryUtil.xCount(vCard, AbilityUtils.getSVar(stAb, addT));
} else {
def = AbilityUtils.calculateAmount(c, addT, stAb);
}
} }
vCard.addPTBoost(att, def, c.getTimestamp(), stAb.getId()); vCard.addPTBoost(att, def, c.getTimestamp(), stAb.getId());
} }

View File

@@ -33,7 +33,6 @@ import forge.game.ability.ApiType;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.card.CardUtil; import forge.game.card.CardUtil;
@@ -938,25 +937,18 @@ public class ComputerUtilCombat {
final CardCollectionView cardList = CardCollection.combine(game.getCardsIn(ZoneType.Battlefield), game.getCardsIn(ZoneType.Command)); final CardCollectionView cardList = CardCollection.combine(game.getCardsIn(ZoneType.Battlefield), game.getCardsIn(ZoneType.Command));
for (final Card card : cardList) { for (final Card card : cardList) {
for (final StaticAbility stAb : card.getStaticAbilities()) { for (final StaticAbility stAb : card.getStaticAbilities()) {
final Map<String, String> params = stAb.getMapParams(); if (!stAb.getParam("Mode").equals("Continuous")) {
if (!params.get("Mode").equals("Continuous")) {
continue; continue;
} }
if (!params.containsKey("Affected") || !params.get("Affected").contains("blocking")) { if (!stAb.hasParam("Affected") || !stAb.getParam("Affected").contains("blocking")) {
continue; continue;
} }
final String valid = TextUtil.fastReplace(params.get("Affected"), "blocking", "Creature"); final String valid = TextUtil.fastReplace(stAb.getParam("Affected"), "blocking", "Creature");
if (!blocker.isValid(valid, card.getController(), card, null)) { if (!blocker.isValid(valid, card.getController(), card, stAb)) {
continue; continue;
} }
if (params.containsKey("AddPower")) { if (stAb.hasParam("AddPower")) {
if (params.get("AddPower").equals("X")) { power += AbilityUtils.calculateAmount(card, stAb.getParam("AddPower"), stAb);
power += CardFactoryUtil.xCount(card, card.getSVar("X"));
} else if (params.get("AddPower").equals("Y")) {
power += CardFactoryUtil.xCount(card, card.getSVar("Y"));
} else {
power += Integer.valueOf(params.get("AddPower"));
}
} }
} }
} }
@@ -1247,25 +1239,18 @@ public class ComputerUtilCombat {
final CardCollectionView cardList = CardCollection.combine(game.getCardsIn(ZoneType.Battlefield), game.getCardsIn(ZoneType.Command)); final CardCollectionView cardList = CardCollection.combine(game.getCardsIn(ZoneType.Battlefield), game.getCardsIn(ZoneType.Command));
for (final Card card : cardList) { for (final Card card : cardList) {
for (final StaticAbility stAb : card.getStaticAbilities()) { for (final StaticAbility stAb : card.getStaticAbilities()) {
final Map<String, String> params = stAb.getMapParams(); if (!stAb.getParam("Mode").equals("Continuous")) {
if (!params.get("Mode").equals("Continuous")) {
continue; continue;
} }
if (!params.containsKey("Affected") || !params.get("Affected").contains("attacking")) { if (!stAb.hasParam("Affected") || !stAb.getParam("Affected").contains("attacking")) {
continue; continue;
} }
final String valid = TextUtil.fastReplace(params.get("Affected"), "attacking", "Creature"); final String valid = TextUtil.fastReplace(stAb.getParam("Affected"), "attacking", "Creature");
if (!attacker.isValid(valid, card.getController(), card, null)) { if (!attacker.isValid(valid, card.getController(), card, stAb)) {
continue; continue;
} }
if (params.containsKey("AddPower")) { if (stAb.hasParam("AddPower")) {
if (params.get("AddPower").equals("X")) { power += AbilityUtils.calculateAmount(card, stAb.getParam("AddPower"), stAb);
power += CardFactoryUtil.xCount(card, card.getSVar("X"));
} else if (params.get("AddPower").equals("Y")) {
power += CardFactoryUtil.xCount(card, card.getSVar("Y"));
} else {
power += Integer.valueOf(params.get("AddPower"));
}
} }
} }
} }
@@ -1339,7 +1324,7 @@ public class ComputerUtilCombat {
} else if (bonus.contains("TriggeredAttacker$CardToughness")) { } else if (bonus.contains("TriggeredAttacker$CardToughness")) {
bonus = TextUtil.fastReplace(bonus, "TriggeredAttacker$CardToughness", TextUtil.concatNoSpace("Number$", String.valueOf(attacker.getNetToughness()))); bonus = TextUtil.fastReplace(bonus, "TriggeredAttacker$CardToughness", TextUtil.concatNoSpace("Number$", String.valueOf(attacker.getNetToughness())));
} }
power += CardFactoryUtil.xCount(source, bonus); power += AbilityUtils.calculateAmount(source, bonus, sa);
} }
} }
@@ -1529,7 +1514,7 @@ public class ComputerUtilCombat {
} else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee } else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee
bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1"); bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1");
} }
toughness += CardFactoryUtil.xCount(source, bonus); toughness += AbilityUtils.calculateAmount(source, bonus, sa);
} }
} else if (ApiType.PumpAll.equals(sa.getApi())) { } else if (ApiType.PumpAll.equals(sa.getApi())) {
@@ -1562,7 +1547,7 @@ public class ComputerUtilCombat {
} else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee } else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee
bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1"); bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1");
} }
toughness += CardFactoryUtil.xCount(source, bonus); toughness += AbilityUtils.calculateAmount(source, bonus, sa);
} }
} }
} }

View File

@@ -157,7 +157,7 @@ public class ComputerUtilCost {
if (typeList.size() > ai.getMaxHandSize()) { if (typeList.size() > ai.getMaxHandSize()) {
continue; continue;
} }
int num = AbilityUtils.calculateAmount(source, disc.getAmount(), null); int num = AbilityUtils.calculateAmount(source, disc.getAmount(), sa);
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
Card pref = ComputerUtil.getCardPreference(ai, source, "DiscardCost", typeList); Card pref = ComputerUtil.getCardPreference(ai, source, "DiscardCost", typeList);

View File

@@ -39,7 +39,6 @@ import forge.game.ability.ApiType;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.card.CardUtil; import forge.game.card.CardUtil;
@@ -1085,7 +1084,7 @@ public class SpecialCardAi {
return false; return false;
} }
String prominentColor = ComputerUtilCard.getMostProminentColor(ai.getCardsIn(ZoneType.Battlefield)); String prominentColor = ComputerUtilCard.getMostProminentColor(ai.getCardsIn(ZoneType.Battlefield));
int devotion = CardFactoryUtil.xCount(sa.getHostCard(), "Count$Devotion." + prominentColor); int devotion = AbilityUtils.calculateAmount(sa.getHostCard(), "Count$Devotion." + prominentColor, sa);
int activationCost = sa.getPayCosts().getTotalMana().getCMC() + (sa.getPayCosts().hasTapCost() ? 1 : 0); int activationCost = sa.getPayCosts().getTotalMana().getCMC() + (sa.getPayCosts().hasTapCost() ? 1 : 0);
// do not use this SA if devotion to most prominent color is less than its own activation cost + 1 (to actually get advantage) // do not use this SA if devotion to most prominent color is less than its own activation cost + 1 (to actually get advantage)

View File

@@ -766,7 +766,7 @@ public class AttachAi extends SpellAbilityAi {
int powerBuff = 0; int powerBuff = 0;
for (StaticAbility stAb : sa.getHostCard().getStaticAbilities()) { for (StaticAbility stAb : sa.getHostCard().getStaticAbilities()) {
if ("Card.EquippedBy".equals(stAb.getParam("Affected")) && stAb.hasParam("AddPower")) { if ("Card.EquippedBy".equals(stAb.getParam("Affected")) && stAb.hasParam("AddPower")) {
powerBuff = AbilityUtils.calculateAmount(sa.getHostCard(), stAb.getParam("AddPower"), null); powerBuff = AbilityUtils.calculateAmount(sa.getHostCard(), stAb.getParam("AddPower"), stAb);
} }
} }
if (combat != null && combat.isAttacking(equipped) && ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS, sa.getActivatingPlayer())) { if (combat != null && combat.isAttacking(equipped) && ph.is(PhaseType.COMBAT_DECLARE_BLOCKERS, sa.getActivatingPlayer())) {

View File

@@ -30,7 +30,6 @@ import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.card.CounterEnumType; import forge.game.card.CounterEnumType;
@@ -132,7 +131,7 @@ public class DamageDealAi extends DamageAiBase {
// Set PayX here to maximum value. It will be adjusted later depending on the target. // Set PayX here to maximum value. It will be adjusted later depending on the target.
sa.setXManaCostPaid(dmg); sa.setXManaCostPaid(dmg);
} else if (sa.getSVar(damage).contains("InYourHand") && source.isInZone(ZoneType.Hand)) { } else if (sa.getSVar(damage).contains("InYourHand") && source.isInZone(ZoneType.Hand)) {
dmg = CardFactoryUtil.xCount(source, sa.getSVar(damage)) - 1; // the card will be spent casting the spell, so actual damage is 1 less dmg = AbilityUtils.calculateAmount(source, damage, sa) - 1; // the card will be spent casting the spell, so actual damage is 1 less
} else if (sa.getSVar(damage).equals("TargetedPlayer$CardsInHand")) { } else if (sa.getSVar(damage).equals("TargetedPlayer$CardsInHand")) {
// cards that deal damage by the number of cards in target player's hand, e.g. Sudden Impact // cards that deal damage by the number of cards in target player's hand, e.g. Sudden Impact
if (sa.getTargetRestrictions().canTgtPlayer()) { if (sa.getTargetRestrictions().canTgtPlayer()) {

View File

@@ -441,7 +441,7 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
} }
if (params.containsKey("WerewolfTransformCondition")) { if (params.containsKey("WerewolfTransformCondition")) {
if (!CardUtil.getLastTurnCast("Card", this.getHostCard()).isEmpty()) { if (!CardUtil.getLastTurnCast("Card", this.getHostCard(), this).isEmpty()) {
return false; return false;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,6 @@ import forge.game.GameObject;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardZoneTable; import forge.game.card.CardZoneTable;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.player.Player; import forge.game.player.Player;
@@ -123,7 +122,7 @@ public abstract class SpellAbilityEffect {
if (sa.hasParam("Announce")) { if (sa.hasParam("Announce")) {
String svar = sa.getParam("Announce"); String svar = sa.getParam("Announce");
int amount = CardFactoryUtil.xCount(sa.getHostCard(), sa.getSVar(svar)); int amount = AbilityUtils.calculateAmount(sa.getHostCard(), svar, sa);
sb.append(" "); sb.append(" ");
sb.append(TextUtil.enclosedParen(TextUtil.concatNoSpace(svar,"=",String.valueOf(amount)))); sb.append(TextUtil.enclosedParen(TextUtil.concatNoSpace(svar,"=",String.valueOf(amount))));
} else{ } else{

View File

@@ -5,11 +5,11 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -127,7 +127,7 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
} }
final String numericAmount = sa.getParamOrDefault("Amount", "1"); final String numericAmount = sa.getParamOrDefault("Amount", "1");
final int validAmount = StringUtils.isNumeric(numericAmount) ? Integer.parseInt(numericAmount) : CardFactoryUtil.xCount(host, host.getSVar(numericAmount)); final int validAmount = StringUtils.isNumeric(numericAmount) ? Integer.parseInt(numericAmount) : AbilityUtils.calculateAmount(host, numericAmount, sa);
for (final Player p : tgtPlayers) { for (final Player p : tgtPlayers) {
final CardCollection chosen = new CardCollection(); final CardCollection chosen = new CardCollection();

View File

@@ -8,7 +8,6 @@ import forge.game.GameObject;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardDamageMap; import forge.game.card.CardDamageMap;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -90,7 +89,7 @@ public class DamageEachEffect extends DamageBaseEffect {
final Card sourceLKI = game.getChangeZoneLKIInfo(source); final Card sourceLKI = game.getChangeZoneLKIInfo(source);
// TODO shouldn't that be using Num or something first? // TODO shouldn't that be using Num or something first?
final int dmg = CardFactoryUtil.xCount(source, sa.getSVar("X")); final int dmg = AbilityUtils.calculateAmount(source, "X", sa);
// System.out.println(source+" deals "+dmg+" damage to "+o.toString()); // System.out.println(source+" deals "+dmg+" damage to "+o.toString());
if (o instanceof Card) { if (o instanceof Card) {
@@ -113,14 +112,14 @@ public class DamageEachEffect extends DamageBaseEffect {
for (final Card source : sources) { for (final Card source : sources) {
final Card sourceLKI = game.getChangeZoneLKIInfo(source); final Card sourceLKI = game.getChangeZoneLKIInfo(source);
final int dmg = CardFactoryUtil.xCount(source, card.getSVar("X")); final int dmg = AbilityUtils.calculateAmount(source, "X", sa);
// System.out.println(source+" deals "+dmg+" damage to "+source); // System.out.println(source+" deals "+dmg+" damage to "+source);
source.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa); source.addDamage(dmg, sourceLKI, damageMap, preventMap, counterTable, sa);
} }
} }
if (sa.getParam("DefinedCards").equals("Remembered")) { if (sa.getParam("DefinedCards").equals("Remembered")) {
for (final Card source : sources) { for (final Card source : sources) {
final int dmg = CardFactoryUtil.xCount(source, card.getSVar("X")); final int dmg = AbilityUtils.calculateAmount(source, "X", sa);
final Card sourceLKI = source.getGame().getChangeZoneLKIInfo(source); final Card sourceLKI = source.getGame().getChangeZoneLKIInfo(source);
for (final Object o : sa.getHostCard().getRemembered()) { for (final Object o : sa.getHostCard().getRemembered()) {

View File

@@ -4,7 +4,6 @@ import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.util.TextUtil; import forge.util.TextUtil;
@@ -50,12 +49,12 @@ public class StoreSVarEffect extends SpellAbilityEffect {
int exprMath = AbilityUtils.calculateAmount(source, exprMathVar, sa); int exprMath = AbilityUtils.calculateAmount(source, exprMathVar, sa);
expr = TextUtil.fastReplace(expr, exprMathVar, Integer.toString(exprMath)); expr = TextUtil.fastReplace(expr, exprMathVar, Integer.toString(exprMath));
} }
value = CardFactoryUtil.xCount(source, "SVar$" + expr); value = AbilityUtils.xCount(source, "SVar$" + expr, sa);
} else if (type.equals("Targeted")) { } else if (type.equals("Targeted")) {
value = CardFactoryUtil.handlePaid(sa.findTargetedCards(), expr, source); value = AbilityUtils.handlePaid(sa.findTargetedCards(), expr, source, sa);
} else if (type.equals("Triggered")) { } else if (type.equals("Triggered")) {
Card trigCard = (Card)sa.getTriggeringObject(AbilityKey.Card); Card trigCard = (Card)sa.getTriggeringObject(AbilityKey.Card);
value = CardFactoryUtil.xCount(trigCard, expr); value = AbilityUtils.xCount(trigCard, expr, sa);
} else if (type.equals("Calculate")) { } else if (type.equals("Calculate")) {
value = AbilityUtils.calculateAmount(source, expr, sa); value = AbilityUtils.calculateAmount(source, expr, sa);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -219,55 +219,22 @@ public class CardProperty {
return false; return false;
} }
} else if (property.equals("TargetedPlayerCtrl")) { } else if (property.equals("TargetedPlayerCtrl")) {
boolean foundTargetingSA = false; if (!AbilityUtils.getDefinedPlayers(source, "TargetedPlayer", spellAbility).contains(controller)) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { return false;
final SpellAbility saTargeting = sa.getSATargetingPlayer();
if (saTargeting != null) {
foundTargetingSA = true;
for (final Player p : saTargeting.getTargets().getTargetPlayers()) {
if (!controller.equals(p)) {
return false;
}
}
}
}
if (!foundTargetingSA) {
// FIXME: Something went wrong with detecting the SA that has a target, this can happen
// e.g. when activating a SA on a card from another player's hand (e.g. opponent's Chandra's Fury
// activated via Sen Triplets). Needs further investigation as to why this is happening, it might
// cause issues elsewhere too.
System.err.println("Warning: could not deduce a player target for TargetedPlayerCtrl for " + source + ", trying to locate it via CastSA...");
SpellAbility castSA = source.getCastSA();
while (castSA != null) {
if (!Iterables.isEmpty(castSA.getTargets().getTargetPlayers())) {
foundTargetingSA = true;
for (final Player p : castSA.getTargets().getTargetPlayers()) {
if (!controller.equals(p)) {
return false;
}
}
}
castSA = castSA.getSubAbility();
}
if (!foundTargetingSA) {
System.err.println("Warning: checking targets in CastSA did not yield any results as well, TargetedPlayerCtrl check failed.");
}
} }
} else if (property.equals("TargetedControllerCtrl")) { } else if (property.equals("TargetedControllerCtrl")) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { final CardCollectionView cards = AbilityUtils.getDefinedCards(source, "Targeted", spellAbility);
final CardCollectionView cards = AbilityUtils.getDefinedCards(source, "Targeted", sa); final List<SpellAbility> sas = AbilityUtils.getDefinedSpellAbilities(source, "Targeted", spellAbility);
final List<SpellAbility> sas = AbilityUtils.getDefinedSpellAbilities(source, "Targeted", sa); for (final Card c : cards) {
for (final Card c : cards) { final Player p = c.getController();
final Player p = c.getController(); if (!controller.equals(p)) {
if (!controller.equals(p)) { return false;
return false;
}
} }
for (final SpellAbility s : sas) { }
final Player p = s.getHostCard().getController(); for (final SpellAbility s : sas) {
if (!controller.equals(p)) { final Player p = s.getHostCard().getController();
return false; if (!controller.equals(p)) {
} return false;
} }
} }
} else if (property.startsWith("ActivePlayerCtrl")) { } else if (property.startsWith("ActivePlayerCtrl")) {
@@ -291,36 +258,8 @@ public class CardProperty {
return false; return false;
} }
} else if (property.equals("TargetedPlayerOwn")) { } else if (property.equals("TargetedPlayerOwn")) {
boolean foundTargetingSA = false; if (!AbilityUtils.getDefinedPlayers(source, "TargetedPlayer", spellAbility).contains(card.getOwner())) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { return false;
final SpellAbility saTargeting = sa.getSATargetingPlayer();
if (saTargeting != null) {
foundTargetingSA = true;
for (final Player p : saTargeting.getTargets().getTargetPlayers()) {
if (!card.getOwner().equals(p)) {
return false;
}
}
}
}
if (!foundTargetingSA) {
// FIXME: Something went wrong with detecting the SA that has a target, needs investigation
System.err.println("Warning: could not deduce a player target for TargetedPlayerOwn for " + source + ", trying to locate it via CastSA...");
SpellAbility castSA = source.getCastSA();
while (castSA != null) {
if (!Iterables.isEmpty(castSA.getTargets().getTargetPlayers())) {
foundTargetingSA = true;
for (final Player p : castSA.getTargets().getTargetPlayers()) {
if (!card.getOwner().equals(p)) {
return false;
}
}
}
castSA = castSA.getSubAbility();
}
if (!foundTargetingSA) {
System.err.println("Warning: checking targets in CastSA did not yield any results as well, TargetedPlayerOwn check failed.");
}
} }
} else if (property.startsWith("OwnedBy")) { } else if (property.startsWith("OwnedBy")) {
final String valid = property.substring(8); final String valid = property.substring(8);
@@ -475,14 +414,9 @@ public class CardProperty {
} }
break; break;
case "Targeted": case "Targeted":
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { for (final Card c : AbilityUtils.getDefinedCards(source, "Targeted", spellAbility)) {
final SpellAbility saTargeting = sa.getSATargetingCard(); if (!card.isEnchantedBy(c) && !card.equals(c.getEntityAttachedTo())) {
if (saTargeting != null) { return false;
for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (!card.isEnchantedBy(c) && !card.equals(c.getEntityAttachedTo())) {
return false;
}
}
} }
} }
break; break;
@@ -497,14 +431,9 @@ public class CardProperty {
} }
} else if (property.startsWith("NotEnchantedBy")) { } else if (property.startsWith("NotEnchantedBy")) {
if (property.substring(14).equals("Targeted")) { if (property.substring(14).equals("Targeted")) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { for (final Card c : AbilityUtils.getDefinedCards(source, "Targeted", spellAbility)) {
final SpellAbility saTargeting = sa.getSATargetingCard(); if (card.isEnchantedBy(c)) {
if (saTargeting != null) { return false;
for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (card.isEnchantedBy(c)) {
return false;
}
}
} }
} }
} else { } else {
@@ -528,14 +457,9 @@ public class CardProperty {
} }
} else if (property.startsWith("CanBeEnchantedBy")) { } else if (property.startsWith("CanBeEnchantedBy")) {
if (property.substring(16).equals("Targeted")) { if (property.substring(16).equals("Targeted")) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { for (final Card c : AbilityUtils.getDefinedCards(source, "Targeted", spellAbility)) {
final SpellAbility saTargeting = sa.getSATargetingCard(); if (!card.canBeAttached(c)) {
if (saTargeting != null) { return false;
for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (!card.canBeAttached(c)) {
return false;
}
}
} }
} }
} else if (property.substring(16).equals("AllRemembered")) { } else if (property.substring(16).equals("AllRemembered")) {
@@ -554,14 +478,9 @@ public class CardProperty {
} }
} else if (property.startsWith("EquippedBy")) { } else if (property.startsWith("EquippedBy")) {
if (property.substring(10).equals("Targeted")) { if (property.substring(10).equals("Targeted")) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { for (final Card c : AbilityUtils.getDefinedCards(source, "Targeted", spellAbility)) {
final SpellAbility saTargeting = sa.getSATargetingCard(); if (!card.hasCardAttachment(c)) {
if (saTargeting != null) { return false;
for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (!card.hasCardAttachment(c)) {
return false;
}
}
} }
} }
} else if (property.substring(10).equals("Enchanted")) { } else if (property.substring(10).equals("Enchanted")) {
@@ -697,18 +616,6 @@ public class CardProperty {
if (!card.getDealtDamageToThisTurn().containsKey(source)) { if (!card.getDealtDamageToThisTurn().containsKey(source)) {
return false; return false;
} }
} else if (property.startsWith("IsTargetingSource")) {
for (final SpellAbility sa : card.getCurrentState().getNonManaAbilities()) {
final SpellAbility saTargeting = sa.getSATargetingCard();
if (saTargeting != null) {
for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (c.equals(source)) {
return true;
}
}
}
}
return false;
} else if (property.startsWith("SharesCMCWith")) { } else if (property.startsWith("SharesCMCWith")) {
if (property.equals("SharesCMCWith")) { if (property.equals("SharesCMCWith")) {
if (!card.sharesCMCWith(source)) { if (!card.sharesCMCWith(source)) {
@@ -916,10 +823,10 @@ public class CardProperty {
} else if (restriction.equals(ZoneType.Battlefield.toString())) { } else if (restriction.equals(ZoneType.Battlefield.toString())) {
return Iterables.any(game.getCardsIn(ZoneType.Battlefield), CardPredicates.sharesNameWith(card)); return Iterables.any(game.getCardsIn(ZoneType.Battlefield), CardPredicates.sharesNameWith(card));
} else if (restriction.equals("ThisTurnCast")) { } else if (restriction.equals("ThisTurnCast")) {
return Iterables.any(CardUtil.getThisTurnCast("Card", source), CardPredicates.sharesNameWith(card)); return Iterables.any(CardUtil.getThisTurnCast("Card", source, spellAbility), CardPredicates.sharesNameWith(card));
} else if (restriction.equals("MovedToGrave")) { } else if (restriction.equals("MovedToGrave")) {
for (final SpellAbility sa : source.getCurrentState().getNonManaAbilities()) { if (!(spellAbility instanceof SpellAbility)) {
final SpellAbility root = sa.getRootAbility(); final SpellAbility root = ((SpellAbility)spellAbility).getRootAbility();
if (root != null && (root.getPaidList("MovedToGrave") != null) if (root != null && (root.getPaidList("MovedToGrave") != null)
&& !root.getPaidList("MovedToGrave").isEmpty()) { && !root.getPaidList("MovedToGrave").isEmpty()) {
final CardCollectionView cards = root.getPaidList("MovedToGrave"); final CardCollectionView cards = root.getPaidList("MovedToGrave");
@@ -1010,7 +917,7 @@ public class CardProperty {
} }
} }
} else if (property.startsWith("SecondSpellCastThisTurn")) { } else if (property.startsWith("SecondSpellCastThisTurn")) {
final List<Card> cards = CardUtil.getThisTurnCast("Card", source); final List<Card> cards = CardUtil.getThisTurnCast("Card", source, spellAbility);
if (cards.size() < 2) { if (cards.size() < 2) {
return false; return false;
} }
@@ -1018,7 +925,7 @@ public class CardProperty {
return false; return false;
} }
} else if (property.equals("ThisTurnCast")) { } else if (property.equals("ThisTurnCast")) {
for (final Card c : CardUtil.getThisTurnCast("Card", source)) { for (final Card c : CardUtil.getThisTurnCast("Card", source, spellAbility)) {
if (card.equals(c)) { if (card.equals(c)) {
return true; return true;
} }
@@ -1067,7 +974,7 @@ public class CardProperty {
return false; return false;
} }
List<Card> cards = CardUtil.getThisTurnEntered(ZoneType.Graveyard, ZoneType.Hand, "Card", source); List<Card> cards = CardUtil.getThisTurnEntered(ZoneType.Graveyard, ZoneType.Hand, "Card", source, spellAbility);
if (!cards.contains(card) && !card.getMadnessWithoutCast()) { if (!cards.contains(card) && !card.getMadnessWithoutCast()) {
return false; return false;
} }

View File

@@ -32,6 +32,7 @@ import forge.card.CardStateName;
import forge.card.CardType; import forge.card.CardType;
import forge.card.ColorSet; import forge.card.ColorSet;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.game.CardTraitBase;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GameObject; import forge.game.GameObject;
@@ -115,7 +116,7 @@ public final class CardUtil {
* @param src a Card object * @param src a Card object
* @return a CardCollection that matches the given criteria * @return a CardCollection that matches the given criteria
*/ */
public static List<Card> getThisTurnEntered(final ZoneType to, final ZoneType from, final String valid, final Card src) { public static List<Card> getThisTurnEntered(final ZoneType to, final ZoneType from, final String valid, final Card src, final CardTraitBase ctb) {
List<Card> res = Lists.newArrayList(); List<Card> res = Lists.newArrayList();
final Game game = src.getGame(); final Game game = src.getGame();
if (to != ZoneType.Stack) { if (to != ZoneType.Stack) {
@@ -126,8 +127,7 @@ public final class CardUtil {
else { else {
res.addAll(game.getStackZone().getCardsAddedThisTurn(from)); res.addAll(game.getStackZone().getCardsAddedThisTurn(from));
} }
res = CardLists.getValidCardsAsList(res, valid, src.getController(), src, null); return CardLists.getValidCardsAsList(res, valid, src.getController(), src, ctb);
return res;
} }
/** /**
@@ -139,7 +139,7 @@ public final class CardUtil {
* @param src a Card object * @param src a Card object
* @return a CardCollection that matches the given criteria * @return a CardCollection that matches the given criteria
*/ */
public static List<Card> getLastTurnEntered(final ZoneType to, final ZoneType from, final String valid, final Card src) { public static List<Card> getLastTurnEntered(final ZoneType to, final ZoneType from, final String valid, final Card src, final CardTraitBase ctb) {
List<Card> res = Lists.newArrayList(); List<Card> res = Lists.newArrayList();
final Game game = src.getGame(); final Game game = src.getGame();
if (to != ZoneType.Stack) { if (to != ZoneType.Stack) {
@@ -150,16 +150,15 @@ public final class CardUtil {
else { else {
res.addAll(game.getStackZone().getCardsAddedLastTurn(from)); res.addAll(game.getStackZone().getCardsAddedLastTurn(from));
} }
res = CardLists.getValidCardsAsList(res, valid, src.getController(), src, null); return CardLists.getValidCardsAsList(res, valid, src.getController(), src, ctb);
return res;
} }
public static List<Card> getThisTurnCast(final String valid, final Card src) { public static List<Card> getThisTurnCast(final String valid, final Card src, final CardTraitBase ctb) {
return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastThisTurn(), valid, src.getController(), src, null); return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastThisTurn(), valid, src.getController(), src, ctb);
} }
public static List<Card> getLastTurnCast(final String valid, final Card src) { public static List<Card> getLastTurnCast(final String valid, final Card src, final CardTraitBase ctb) {
return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastLastTurn(), valid, src.getController(), src, null); return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastLastTurn(), valid, src.getController(), src, ctb);
} }

View File

@@ -18,7 +18,6 @@ import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.card.CardUtil; import forge.game.card.CardUtil;
@@ -139,9 +138,9 @@ public class CostAdjustment {
count = Integer.parseInt(amount); count = Integer.parseInt(amount);
} else { } else {
if (st.hasParam("AffectedAmount")) { if (st.hasParam("AffectedAmount")) {
count = CardFactoryUtil.xCount(card, hostCard.getSVar(amount)); count = AbilityUtils.calculateAmount(card, amount, st);
} else { } else {
count = AbilityUtils.calculateAmount(hostCard, amount, sa); count = AbilityUtils.calculateAmount(hostCard, amount, st);
} }
} }
} }
@@ -380,7 +379,7 @@ public class CostAdjustment {
int value; int value;
if ("AffectedX".equals(amount)) { if ("AffectedX".equals(amount)) {
value = CardFactoryUtil.xCount(card, hostCard.getSVar(amount)); value = AbilityUtils.calculateAmount(card, amount, staticAbility);
} else if ("Undaunted".equals(amount)) { } else if ("Undaunted".equals(amount)) {
value = card.getController().getOpponents().size(); value = card.getController().getOpponents().size();
} else if (staticAbility.hasParam("Relative")) { } else if (staticAbility.hasParam("Relative")) {
@@ -429,13 +428,13 @@ public class CostAdjustment {
final Card card = sa.getHostCard(); final Card card = sa.getHostCard();
final Game game = hostCard.getGame(); final Game game = hostCard.getGame();
if (st.hasParam("ValidCard") && !st.matchesValid(card, st.getParam("ValidCard").split(","))) { if (!st.matchesValidParam("ValidCard", card)) {
return false; return false;
} }
if (st.hasParam("ValidSpell") && !st.matchesValid(sa, st.getParam("ValidSpell").split(","))) { if (!st.matchesValidParam("ValidSpell", sa)) {
return false; return false;
} }
if (st.hasParam("Activator") && !st.matchesValid(activator, st.getParam("Activator").split(","))) { if (!st.matchesValidParam("Activator", activator)) {
return false; return false;
} }
if (st.hasParam("NonActivatorTurn") && ((activator == null) if (st.hasParam("NonActivatorTurn") && ((activator == null)
@@ -455,7 +454,7 @@ public class CostAdjustment {
} }
List<Card> list; List<Card> list;
if (st.hasParam("ValidCard")) { if (st.hasParam("ValidCard")) {
list = CardUtil.getThisTurnCast(st.getParam("ValidCard"), hostCard); list = CardUtil.getThisTurnCast(st.getParam("ValidCard"), hostCard, st);
} else { } else {
list = game.getStack().getSpellsCastThisTurn(); list = game.getStack().getSpellsCastThisTurn();
} }

View File

@@ -30,7 +30,6 @@ import forge.game.GameType;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPlayOption; import forge.game.card.CardPlayOption;
import forge.game.card.CardUtil; import forge.game.card.CardUtil;
@@ -455,13 +454,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
life = activator.getOpponentsSmallestLifeTotal(); life = activator.getOpponentsSmallestLifeTotal();
} }
int right = 1; int right =AbilityUtils.calculateAmount(sa.getHostCard(), this.getLifeAmount().substring(2), sa);
final String rightString = this.getLifeAmount().substring(2);
if (rightString.equals("X")) {
right = CardFactoryUtil.xCount(sa.getHostCard(), sa.getHostCard().getSVar("X"));
} else {
right = Integer.parseInt(this.getLifeAmount().substring(2));
}
if (!Expressions.compare(life, this.getLifeAmount(), right)) { if (!Expressions.compare(life, this.getLifeAmount(), right)) {
return false; return false;

View File

@@ -23,7 +23,6 @@ import forge.game.GameEntity;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.cost.Cost; import forge.game.cost.Cost;
import forge.game.keyword.KeywordInterface; import forge.game.keyword.KeywordInterface;
@@ -199,7 +198,7 @@ public class StaticAbilityCantAttackBlock {
} }
String costString = stAb.getParam("Cost"); String costString = stAb.getParam("Cost");
if (stAb.hasSVar(costString)) { if (stAb.hasSVar(costString)) {
costString = Integer.toString(CardFactoryUtil.xCount(hostCard, stAb.getSVar(costString))); costString = Integer.toString(AbilityUtils.calculateAmount(hostCard, costString, stAb));
} }
return new Cost(costString, true); return new Cost(costString, true);

View File

@@ -132,7 +132,7 @@ public class StaticAbilityCantBeCast {
if (stAb.hasParam("NumLimitEachTurn") && activator != null) { if (stAb.hasParam("NumLimitEachTurn") && activator != null) {
int limit = Integer.parseInt(stAb.getParam("NumLimitEachTurn")); int limit = Integer.parseInt(stAb.getParam("NumLimitEachTurn"));
String valid = stAb.hasParam("ValidCard") ? stAb.getParam("ValidCard") : "Card"; String valid = stAb.hasParam("ValidCard") ? stAb.getParam("ValidCard") : "Card";
List<Card> thisTurnCast = CardUtil.getThisTurnCast(valid, card); List<Card> thisTurnCast = CardUtil.getThisTurnCast(valid, card, stAb);
if (CardLists.filterControlledBy(thisTurnCast, activator).size() < limit) { if (CardLists.filterControlledBy(thisTurnCast, activator).size() < limit) {
return false; return false;
} }

View File

@@ -638,11 +638,11 @@ public final class StaticAbilityContinuous {
if (layer == StaticAbilityLayer.SETPT) { if (layer == StaticAbilityLayer.SETPT) {
if ((setPower != Integer.MAX_VALUE) || (setToughness != Integer.MAX_VALUE)) { if ((setPower != Integer.MAX_VALUE) || (setToughness != Integer.MAX_VALUE)) {
// non CharacteristicDefining // non CharacteristicDefining
if (setP.startsWith("AffectedX")) { if (setP.startsWith("Affected")) {
setPower = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, setP)); setPower = AbilityUtils.calculateAmount(affectedCard, setP, stAb, true);
} }
if (setT.startsWith("AffectedX")) { if (setT.startsWith("Affected")) {
setToughness = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, setT)); setToughness = AbilityUtils.calculateAmount(affectedCard, setT, stAb, true);
} }
affectedCard.addNewPT(setPower, setToughness, affectedCard.addNewPT(setPower, setToughness,
hostCard.getTimestamp(), stAb.hasParam("CharacteristicDefining")); hostCard.getTimestamp(), stAb.hasParam("CharacteristicDefining"));
@@ -651,11 +651,11 @@ public final class StaticAbilityContinuous {
// add P/T bonus // add P/T bonus
if (layer == StaticAbilityLayer.MODIFYPT) { if (layer == StaticAbilityLayer.MODIFYPT) {
if (addP.startsWith("AffectedX")) { if (addP.startsWith("Affected")) {
powerBonus = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, addP)); powerBonus = AbilityUtils.calculateAmount(affectedCard, addP, stAb, true);
} }
if (addT.startsWith("AffectedX")) { if (addT.startsWith("Affected")) {
toughnessBonus = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, addT)); toughnessBonus = AbilityUtils.calculateAmount(affectedCard, addT, stAb, true);
} }
affectedCard.addPTBoost(powerBonus, toughnessBonus, se.getTimestamp(), stAb.getId()); affectedCard.addPTBoost(powerBonus, toughnessBonus, se.getTimestamp(), stAb.getId());
} }

View File

@@ -30,7 +30,6 @@ import com.google.common.collect.Sets;
import forge.game.ability.AbilityKey; import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists; import forge.game.card.CardLists;
import forge.game.card.CardPredicates; import forge.game.card.CardPredicates;
import forge.game.card.CardUtil; import forge.game.card.CardUtil;
@@ -139,7 +138,7 @@ public class TriggerChangesZone extends Trigger {
final String comparator = condition.length < 2 ? "GE1" : condition[1]; final String comparator = condition.length < 2 ? "GE1" : condition[1];
final int referenceValue = AbilityUtils.calculateAmount(host, comparator.substring(2), this); final int referenceValue = AbilityUtils.calculateAmount(host, comparator.substring(2), this);
final Card triggered = (Card) runParams.get(AbilityKey.Card); final Card triggered = (Card) runParams.get(AbilityKey.Card);
final int actualValue = CardFactoryUtil.xCount(triggered, host.getSVar(condition[0])); final int actualValue = AbilityUtils.calculateAmount(triggered, condition[0], this);
if (!Expressions.compare(actualValue, comparator.substring(0, 2), referenceValue)) { if (!Expressions.compare(actualValue, comparator.substring(0, 2), referenceValue)) {
return false; return false;
} }
@@ -179,7 +178,7 @@ public class TriggerChangesZone extends Trigger {
/* this trigger only activates for the nth spell you cast this turn */ /* this trigger only activates for the nth spell you cast this turn */
if (hasParam("ConditionYouCastThisTurn")) { if (hasParam("ConditionYouCastThisTurn")) {
final String compare = getParam("ConditionYouCastThisTurn"); final String compare = getParam("ConditionYouCastThisTurn");
List<Card> thisTurnCast = CardUtil.getThisTurnCast("Card", getHostCard()); List<Card> thisTurnCast = CardUtil.getThisTurnCast("Card", getHostCard(), this);
thisTurnCast = CardLists.filterControlledByAsList(thisTurnCast, getHostCard().getController()); thisTurnCast = CardLists.filterControlledByAsList(thisTurnCast, getHostCard().getController());
// checks which card this spell was the castSA // checks which card this spell was the castSA

View File

@@ -109,7 +109,7 @@ public class TriggerSpellAbilityCastOrCopy extends Trigger {
if (hasParam("ActivatorThisTurnCast")) { if (hasParam("ActivatorThisTurnCast")) {
final String compare = getParam("ActivatorThisTurnCast"); final String compare = getParam("ActivatorThisTurnCast");
final String valid = hasParam("ValidCard") ? getParam("ValidCard") : "Card"; final String valid = hasParam("ValidCard") ? getParam("ValidCard") : "Card";
List<Card> thisTurnCast = CardUtil.getThisTurnCast(valid, getHostCard()); List<Card> thisTurnCast = CardUtil.getThisTurnCast(valid, getHostCard(), this);
thisTurnCast = CardLists.filterControlledBy(thisTurnCast, si.getSpellAbility(true).getActivatingPlayer()); thisTurnCast = CardLists.filterControlledBy(thisTurnCast, si.getSpellAbility(true).getActivatingPlayer());
int left = thisTurnCast.size(); int left = thisTurnCast.size();
int right = Integer.parseInt(compare.substring(2)); int right = Integer.parseInt(compare.substring(2));

View File

@@ -5,5 +5,4 @@ A:SP$ DealDamage | Cost$ 3 R | ValidTgts$ Player | TgtPrompt$ Select target play
SVar:X:TargetedPlayer$LifeTotal SVar:X:TargetedPlayer$LifeTotal
SVar:Y:Count$OppsAtLifeTotal.10 SVar:Y:Count$OppsAtLifeTotal.10
SVar:NeedsToPlayVar:Y GE1 SVar:NeedsToPlayVar:Y GE1
SVar:Picture:http://resources.wizards.com/magic/cards/sok/en-us/card88818.jpg Oracle:If target player has exactly 10 life, Hidetsugu's Second Rite deals 10 damage to that player.
Oracle:If target player has exactly 10 life, Hidetsugu's Second Rite deals 10 damage to that player.

View File

@@ -11,5 +11,5 @@ SVar:STPlay:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | Effect
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$ValidHand Card.DefenderCtrl SVar:X:Count$ValidHand Card.DefenderCtrl
SVar:Y:Count$InYourHand SVar:Y:Count$InYourHand
SVar:Z:Count$CreaturesAttackedThisTurn_Rogue SVar:Z:Count$CreaturesAttackedThisTurn Creature.Rogue
Oracle:Reach, haste\nWhenever Robber of the Rich attacks, if defending player has more cards in hand than you, exile the top card of their library. During any turn you attacked with a Rogue, you may cast that card and you may spend mana as though it were mana of any color to cast that spell. Oracle:Reach, haste\nWhenever Robber of the Rich attacks, if defending player has more cards in hand than you, exile the top card of their library. During any turn you attacked with a Rogue, you may cast that card and you may spend mana as though it were mana of any color to cast that spell.

View File

@@ -412,8 +412,7 @@ public final class CardScriptParser {
"notTributed", "madness", "Paired", "NotPaired", "PairedWith", "notTributed", "madness", "Paired", "NotPaired", "PairedWith",
"Above", "DirectlyAbove", "TopGraveyardCreature", "Above", "DirectlyAbove", "TopGraveyardCreature",
"BottomGraveyard", "TopLibrary", "Cloned", "DamagedBy", "Damaged", "BottomGraveyard", "TopLibrary", "Cloned", "DamagedBy", "Damaged",
"IsTargetingSource", "sharesPermanentTypeWith", "sharesPermanentTypeWith", "canProduceSameManaTypeWith", "SecondSpellCastThisTurn",
"canProduceSameManaTypeWith", "SecondSpellCastThisTurn",
"ThisTurnCast", "withFlashback", "tapped", "untapped", "faceDown", "ThisTurnCast", "withFlashback", "tapped", "untapped", "faceDown",
"faceUp", "hasLevelUp", "DrawnThisTurn", "notDrawnThisTurn", "faceUp", "hasLevelUp", "DrawnThisTurn", "notDrawnThisTurn",
"firstTurnControlled", "notFirstTurnControlled", "firstTurnControlled", "notFirstTurnControlled",