mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Card property targeted player
This commit is contained in:
committed by
Michael Kamensky
parent
cad42948cd
commit
ff7f81c307
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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())) {
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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
@@ -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{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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.
|
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user