mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
- Added the new static ability CantAttackUnless.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -12177,6 +12177,7 @@ src/main/java/forge/card/spellability/TargetChoices.java svneol=native#text/plai
|
|||||||
src/main/java/forge/card/spellability/TargetSelection.java svneol=native#text/plain
|
src/main/java/forge/card/spellability/TargetSelection.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/spellability/package-info.java svneol=native#text/plain
|
src/main/java/forge/card/spellability/package-info.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/staticability/StaticAbility.java svneol=native#text/plain
|
src/main/java/forge/card/staticability/StaticAbility.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/card/staticability/StaticAbilityCantAttackBlock.java -text
|
||||||
src/main/java/forge/card/staticability/StaticAbilityCantBeCast.java svneol=native#text/plain
|
src/main/java/forge/card/staticability/StaticAbilityCantBeCast.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/staticability/StaticAbilityCantTarget.java -text
|
src/main/java/forge/card/staticability/StaticAbilityCantTarget.java -text
|
||||||
src/main/java/forge/card/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
src/main/java/forge/card/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Enchantment Aura
|
|||||||
Text:no text
|
Text:no text
|
||||||
K:Enchant creature
|
K:Enchant creature
|
||||||
A:SP$ Attach | Cost$ W | ValidTgts$ Creature | AILogic$ Curse
|
A:SP$ Attach | Cost$ W | ValidTgts$ Creature | AILogic$ Curse
|
||||||
K:Creatures can't attack unless their controller pays:Creature.AttachedBy:3:Enchanted creature can't attack unless its controller pays 3.
|
S:Mode$ CantAttackUnless | ValidCard$ Creature.AttachedBy | Cost$ 3 | Description$ Enchanted creature can't attack unless its controller pays 3.
|
||||||
SVar:Rarity:Common
|
SVar:Rarity:Common
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/brainwash.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/brainwash.jpg
|
||||||
SetInfo:5ED|Common|http://magiccards.info/scans/en/5e/289.jpg
|
SetInfo:5ED|Common|http://magiccards.info/scans/en/5e/289.jpg
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Collective Restraint
|
|||||||
ManaCost:3 U
|
ManaCost:3 U
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
Text:no text
|
Text:no text
|
||||||
K:Creatures can't attack unless their controller pays:Creature.YouDontCtrl:X:Domain - Creatures can't attack you unless their controller pays X for each creature he or she controls that's attacking you, where X is the number of basic land types among lands you control.
|
S:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You | Cost$ X | Description$ Domain - Creatures can't attack you unless their controller pays X for each creature he or she controls that's attacking you, where X is the number of basic land types among lands you control.
|
||||||
SVar:X:Count$Domain
|
SVar:X:Count$Domain
|
||||||
SVar:Rarity:Rare
|
SVar:Rarity:Rare
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/collective_restraint.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/collective_restraint.jpg
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Enchantment
|
|||||||
Text:no text
|
Text:no text
|
||||||
K:Cumulative upkeep:1
|
K:Cumulative upkeep:1
|
||||||
S:Mode$ Continuous | Affected$ Creature.Black+YouDontCtrl | AddHiddenKeyword$ HIDDEN CARDNAME can't attack. | Description$ Black creatures can't attack you.
|
S:Mode$ Continuous | Affected$ Creature.Black+YouDontCtrl | AddHiddenKeyword$ HIDDEN CARDNAME can't attack. | Description$ Black creatures can't attack you.
|
||||||
K:Creatures can't attack unless their controller pays:Creature.nonBlack+YouDontCtrl:2:Nonblack creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
S:Mode$ CantAttackUnless | ValidCard$ Creature.nonBlack | Target$ You | Cost$ 2 | Description$ Nonblack creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||||
SVar:Rarity:Uncommon
|
SVar:Rarity:Uncommon
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/elephant_grass.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/elephant_grass.jpg
|
||||||
SetInfo:VIS|Uncommon|http://magiccards.info/scans/en/vi/54.jpg
|
SetInfo:VIS|Uncommon|http://magiccards.info/scans/en/vi/54.jpg
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Ghostly Prison
|
|||||||
ManaCost:2 W
|
ManaCost:2 W
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
Text:no text
|
Text:no text
|
||||||
K:Creatures can't attack unless their controller pays:Creature.YouDontCtrl:2:Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
S:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You | Cost$ 2 | Description$ Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||||
SVar:Rarity:Uncommon
|
SVar:Rarity:Uncommon
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/ghostly_prison.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/ghostly_prison.jpg
|
||||||
SetInfo:CHK|Uncommon|http://magiccards.info/scans/en/chk/10.jpg
|
SetInfo:CHK|Uncommon|http://magiccards.info/scans/en/chk/10.jpg
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Artifact Creature Construct
|
|||||||
Text:no text
|
Text:no text
|
||||||
PT:0/0
|
PT:0/0
|
||||||
K:CARDNAME can't block.
|
K:CARDNAME can't block.
|
||||||
K:Creatures can't attack unless their controller pays:Card.Self:Y:CARDNAME can't attack unless you pay 1 for each +1/+1 counter on it.
|
S:Mode$ CantAttackUnless | ValidCard$ Card.Self | Cost$ Y | Description$ CARDNAME can't attack unless you pay 1 for each +1/+1 counter on it.
|
||||||
K:etbCounter:P1P1:X
|
K:etbCounter:P1P1:X
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
SVar:Y:Count$NumCounters.P1P1
|
SVar:Y:Count$NumCounters.P1P1
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Propaganda
|
|||||||
ManaCost:2 U
|
ManaCost:2 U
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
Text:no text
|
Text:no text
|
||||||
K:Creatures can't attack unless their controller pays:Creature.YouDontCtrl:2:Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
S:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You | Cost$ 2 | Description$ Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||||
SVar:Rarity:Uncommon
|
SVar:Rarity:Uncommon
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/propaganda.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/propaganda.jpg
|
||||||
SetInfo:TMP|Uncommon|http://magiccards.info/scans/en/tp/80.jpg
|
SetInfo:TMP|Uncommon|http://magiccards.info/scans/en/tp/80.jpg
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Windborn Muse
|
|||||||
ManaCost:3 W
|
ManaCost:3 W
|
||||||
Types:Creature Spirit
|
Types:Creature Spirit
|
||||||
Text:no text
|
Text:no text
|
||||||
K:Creatures can't attack unless their controller pays:Creature.YouDontCtrl:2:Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
S:Mode$ CantAttackUnless | ValidCard$ Creature | Target$ You | Cost$ 2 | Description$ Creatures can't attack you unless their controller pays 2 for each creature he or she controls that's attacking you.
|
||||||
PT:2/3
|
PT:2/3
|
||||||
K:Flying
|
K:Flying
|
||||||
SVar:Rarity:Rare
|
SVar:Rarity:Rare
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import forge.card.cost.CostMana;
|
|||||||
import forge.card.cost.CostPutCounter;
|
import forge.card.cost.CostPutCounter;
|
||||||
import forge.card.cost.CostReturn;
|
import forge.card.cost.CostReturn;
|
||||||
import forge.card.cost.CostSacrifice;
|
import forge.card.cost.CostSacrifice;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.cost.CostUtil;
|
||||||
import forge.card.spellability.Ability;
|
import forge.card.spellability.Ability;
|
||||||
import forge.card.spellability.AbilityMana;
|
import forge.card.spellability.AbilityMana;
|
||||||
import forge.card.spellability.AbilitySub;
|
import forge.card.spellability.AbilitySub;
|
||||||
@@ -447,7 +447,8 @@ public final class GameActionUtil {
|
|||||||
* a {@link forge.Command} object.
|
* a {@link forge.Command} object.
|
||||||
* @param sourceAbility TODO
|
* @param sourceAbility TODO
|
||||||
*/
|
*/
|
||||||
public static void payCostDuringAbilityResolve(final SpellAbility ability, final Cost cost, final Command paid, final Command unpaid, SpellAbility sourceAbility) {
|
public static void payCostDuringAbilityResolve(final SpellAbility ability, final Cost cost, final Command paid,
|
||||||
|
final Command unpaid, SpellAbility sourceAbility) {
|
||||||
final Card source = ability.getSourceCard();
|
final Card source = ability.getSourceCard();
|
||||||
final ArrayList<CostPart> parts = cost.getCostParts();
|
final ArrayList<CostPart> parts = cost.getCostParts();
|
||||||
if (parts.size() > 1) {
|
if (parts.size() > 1) {
|
||||||
@@ -1687,24 +1688,7 @@ public final class GameActionUtil {
|
|||||||
public static Cost combineCosts(SpellAbility sa, String additionalCost) {
|
public static Cost combineCosts(SpellAbility sa, String additionalCost) {
|
||||||
final Cost newCost = new Cost(sa.getSourceCard(), additionalCost, false);
|
final Cost newCost = new Cost(sa.getSourceCard(), additionalCost, false);
|
||||||
Cost oldCost = sa.getPayCosts();
|
Cost oldCost = sa.getPayCosts();
|
||||||
if (sa.getPayCosts() != null) {
|
return CostUtil.combineCosts(oldCost, newCost);
|
||||||
for (final CostPart part : oldCost.getCostParts()) {
|
|
||||||
if (!(part instanceof CostMana)) {
|
|
||||||
newCost.getCostParts().add(part);
|
|
||||||
} else {
|
|
||||||
CostMana newCostMana = newCost.getCostMana();
|
|
||||||
if (newCostMana != null) {
|
|
||||||
ManaCost oldManaCost = new ManaCost(part.toString());
|
|
||||||
newCostMana.setXMana(oldManaCost.getXcounter() + newCostMana.getXMana());
|
|
||||||
oldManaCost.combineManaCost(newCostMana.toString());
|
|
||||||
newCostMana.setMana(oldManaCost.toString(false));
|
|
||||||
} else {
|
|
||||||
newCost.getCostParts().add(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newCost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3433,48 +3433,6 @@ public class CardFactoryUtil {
|
|||||||
return maxColor;
|
return maxColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Get the total cost to pay for an attacker c, due to cards like
|
|
||||||
* Propaganda, Ghostly Prison, Collective Restraint, ...
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param c
|
|
||||||
* a {@link forge.Card} object.
|
|
||||||
* @return a {@link java.lang.String} object.
|
|
||||||
*/
|
|
||||||
public static String getPropagandaCost(final Card c) {
|
|
||||||
int cost = 0;
|
|
||||||
|
|
||||||
final CardList list = AllZoneUtil.getCardsIn(ZoneType.Battlefield);
|
|
||||||
for (final Card card : list) {
|
|
||||||
if (card.hasStartOfKeyword("Creatures can't attack unless their controller pays")) {
|
|
||||||
final int keywordPosition = card
|
|
||||||
.getKeywordPosition("Creatures can't attack unless their controller pays");
|
|
||||||
final String parse = card.getKeyword().get(keywordPosition).toString();
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
|
|
||||||
final String[] restrictions = k[1].split(",");
|
|
||||||
if (!c.isValid(restrictions, card.getController(), card)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String costString = k[2];
|
|
||||||
if (costString.equals("X")) {
|
|
||||||
cost += CardFactoryUtil.xCount(card, card.getSVar("X"));
|
|
||||||
} else if (costString.equals("Y")) {
|
|
||||||
cost += CardFactoryUtil.xCount(card, card.getSVar("Y"));
|
|
||||||
} else {
|
|
||||||
cost += Integer.parseInt(k[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String s = Integer.toString(cost);
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* getUsableManaSources.
|
* getUsableManaSources.
|
||||||
|
|||||||
@@ -184,7 +184,11 @@ public class Cost {
|
|||||||
public Cost(final Card card, String parse, final boolean bAbility) {
|
public Cost(final Card card, String parse, final boolean bAbility) {
|
||||||
this.isAbility = bAbility;
|
this.isAbility = bAbility;
|
||||||
// when adding new costs for cost string, place them here
|
// when adding new costs for cost string, place them here
|
||||||
this.name = card.getName();
|
String name = "";
|
||||||
|
if (card != null) {
|
||||||
|
name = card.getName();
|
||||||
|
}
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
while (parse.contains(Cost.TAP_X_STR)) {
|
while (parse.contains(Cost.TAP_X_STR)) {
|
||||||
final String[] splitStr = this.abCostParse(parse, Cost.TAP_X_STR, 3);
|
final String[] splitStr = this.abCostParse(parse, Cost.TAP_X_STR, 3);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import forge.Card;
|
|||||||
import forge.CardList;
|
import forge.CardList;
|
||||||
import forge.Counters;
|
import forge.Counters;
|
||||||
import forge.card.abilityfactory.AbilityFactory;
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
import forge.game.player.ComputerUtil;
|
import forge.game.player.ComputerUtil;
|
||||||
@@ -456,4 +457,36 @@ public class CostUtil {
|
|||||||
// Just a shortcut..
|
// Just a shortcut..
|
||||||
AllZone.getInputControl().setInput(in, true);
|
AllZone.getInputControl().setInput(in, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Cost combineCosts(Cost cost1, Cost cost2) {
|
||||||
|
if (cost1 == null) {
|
||||||
|
if (cost2 == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return cost2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cost2 == null) {
|
||||||
|
return cost1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final CostPart part : cost1.getCostParts()) {
|
||||||
|
if (!(part instanceof CostMana)) {
|
||||||
|
cost2.getCostParts().add(part);
|
||||||
|
} else {
|
||||||
|
CostMana newCostMana = cost2.getCostMana();
|
||||||
|
if (newCostMana != null) {
|
||||||
|
ManaCost oldManaCost = new ManaCost(part.toString());
|
||||||
|
newCostMana.setXMana(oldManaCost.getXcounter() + newCostMana.getXMana());
|
||||||
|
oldManaCost.combineManaCost(newCostMana.toString());
|
||||||
|
newCostMana.setMana(oldManaCost.toString(false));
|
||||||
|
} else {
|
||||||
|
cost2.getCostParts().add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cost2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import forge.Card;
|
|||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.abilityfactory.AbilityFactory;
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
@@ -408,6 +409,39 @@ public class StaticAbility {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply ability.
|
||||||
|
*
|
||||||
|
* @param mode
|
||||||
|
* the mode
|
||||||
|
* @param card
|
||||||
|
* the card
|
||||||
|
* @param target
|
||||||
|
* the target
|
||||||
|
* @return true, if successful
|
||||||
|
*/
|
||||||
|
public final Cost getCostAbility(final String mode, final Card card, final GameEntity target) {
|
||||||
|
|
||||||
|
// don't apply the ability if it hasn't got the right mode
|
||||||
|
if (!this.mapParams.get("Mode").equals(mode)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isSuppressed() || !this.checkConditions()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("CantAttackUnless")) {
|
||||||
|
return StaticAbilityCantAttackBlock.applyCantAttackUnlessAbility(this, card, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("CantBlockUnless")) {
|
||||||
|
return StaticAbilityCantAttackBlock.applyCantBlockUnlessAbility(this, card);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check conditions.
|
* Check conditions.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Forge: Play Magic: the Gathering.
|
||||||
|
* Copyright (C) 2011 Forge Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package forge.card.staticability;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.GameEntity;
|
||||||
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class StaticAbility_CantBeCast.
|
||||||
|
*/
|
||||||
|
public class StaticAbilityCantAttackBlock{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO Write javadoc for this method.
|
||||||
|
*
|
||||||
|
* @param stAb
|
||||||
|
* a StaticAbility
|
||||||
|
* @param card
|
||||||
|
* the card
|
||||||
|
* @return a Cost
|
||||||
|
*/
|
||||||
|
public static Cost applyCantAttackUnlessAbility(final StaticAbility stAb, final Card card, final GameEntity target) {
|
||||||
|
final HashMap<String, String> params = stAb.getMapParams();
|
||||||
|
final Card hostCard = stAb.getHostCard();
|
||||||
|
|
||||||
|
if (params.containsKey("ValidCard")
|
||||||
|
&& !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("Target")
|
||||||
|
&& !target.isValid(params.get("Target").split(","), hostCard.getController(), hostCard)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String costString = params.get("Cost");
|
||||||
|
if ("X".equals(costString)) {
|
||||||
|
costString = Integer.toString(CardFactoryUtil.xCount(hostCard, hostCard.getSVar("X")));
|
||||||
|
} else if ("Y".equals(costString)) {
|
||||||
|
costString = Integer.toString(CardFactoryUtil.xCount(hostCard, hostCard.getSVar("Y")));
|
||||||
|
}
|
||||||
|
|
||||||
|
final Cost cost = new Cost(hostCard, costString, true);
|
||||||
|
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO Write javadoc for this method.
|
||||||
|
*
|
||||||
|
* @param stAb
|
||||||
|
* a StaticAbility
|
||||||
|
* @param card
|
||||||
|
* the card
|
||||||
|
* @return a Cost
|
||||||
|
*/
|
||||||
|
public static Cost applyCantBlockUnlessAbility(final StaticAbility stAb, final Card card) {
|
||||||
|
final HashMap<String, String> params = stAb.getMapParams();
|
||||||
|
final Card hostCard = stAb.getHostCard();
|
||||||
|
|
||||||
|
if (params.containsKey("ValidCard")
|
||||||
|
&& !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Cost cost = new Cost(hostCard, params.get("Cost"), true);
|
||||||
|
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -43,14 +43,16 @@ import forge.card.TriggerReplacementBase;
|
|||||||
import forge.card.abilityfactory.AbilityFactory;
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
import forge.card.abilityfactory.AbilityFactorySacrifice;
|
import forge.card.abilityfactory.AbilityFactorySacrifice;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.cost.CostUtil;
|
||||||
import forge.card.spellability.Ability;
|
import forge.card.spellability.Ability;
|
||||||
import forge.card.spellability.AbilityActivated;
|
import forge.card.spellability.AbilityActivated;
|
||||||
|
import forge.card.spellability.AbilityStatic;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.staticability.StaticAbility;
|
import forge.card.staticability.StaticAbility;
|
||||||
import forge.card.trigger.Trigger;
|
import forge.card.trigger.Trigger;
|
||||||
import forge.card.trigger.TriggerHandler;
|
import forge.card.trigger.TriggerHandler;
|
||||||
import forge.card.trigger.TriggerType;
|
import forge.card.trigger.TriggerType;
|
||||||
import forge.control.input.InputPayManaCostAbility;
|
|
||||||
import forge.game.player.ComputerUtil;
|
import forge.game.player.ComputerUtil;
|
||||||
import forge.game.player.ComputerUtilBlock;
|
import forge.game.player.ComputerUtilBlock;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -2650,8 +2652,16 @@ public class CombatUtil {
|
|||||||
* a boolean.
|
* a boolean.
|
||||||
*/
|
*/
|
||||||
public static void checkPropagandaEffects(final Card c, final boolean bLast) {
|
public static void checkPropagandaEffects(final Card c, final boolean bLast) {
|
||||||
final String cost = CardFactoryUtil.getPropagandaCost(c);
|
Cost attackCost = new Cost(c, "0", true);
|
||||||
if (cost.equals("0")) {
|
// Sort abilities to apply them in proper order
|
||||||
|
for (Card card : AllZoneUtil.getCardsIn(ZoneType.Battlefield)) {
|
||||||
|
final ArrayList<StaticAbility> staticAbilities = card.getStaticAbilities();
|
||||||
|
for (final StaticAbility stAb : staticAbilities) {
|
||||||
|
Cost additionalCost = stAb.getCostAbility("CantAttackUnless", c, AllZone.getCombat().getDefenderByAttacker(c));
|
||||||
|
attackCost = CostUtil.combineCosts(attackCost, additionalCost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attackCost.toSimpleString().equals("")) {
|
||||||
if (!c.hasKeyword("Vigilance")) {
|
if (!c.hasKeyword("Vigilance")) {
|
||||||
c.tap();
|
c.tap();
|
||||||
}
|
}
|
||||||
@@ -2667,63 +2677,59 @@ public class CombatUtil {
|
|||||||
final PhaseType phase = Singletons.getModel().getGameState().getPhaseHandler().getPhase();
|
final PhaseType phase = Singletons.getModel().getGameState().getPhaseHandler().getPhase();
|
||||||
|
|
||||||
if (phase == PhaseType.COMBAT_DECLARE_ATTACKERS || phase == PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) {
|
if (phase == PhaseType.COMBAT_DECLARE_ATTACKERS || phase == PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) {
|
||||||
if (!cost.equals("0")) {
|
final Ability ability = new AbilityStatic(c, attackCost, null) {
|
||||||
final Ability ability = new Ability(c, cost) {
|
@Override
|
||||||
@Override
|
public void resolve() {
|
||||||
public void resolve() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final Command unpaidCommand = new Command() {
|
final Command unpaidCommand = new Command() {
|
||||||
|
|
||||||
private static final long serialVersionUID = -6483405139208343935L;
|
private static final long serialVersionUID = -6483405139208343935L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
AllZone.getCombat().removeFromCombat(crd);
|
AllZone.getCombat().removeFromCombat(crd);
|
||||||
|
|
||||||
if (bLast) {
|
|
||||||
PhaseUtil.handleAttackingTriggers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
final Command paidCommand = new Command() {
|
|
||||||
private static final long serialVersionUID = -8303368287601871955L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
// if Propaganda is paid, tap this card
|
|
||||||
if (!crd.hasKeyword("Vigilance")) {
|
|
||||||
crd.tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bLast) {
|
|
||||||
PhaseUtil.handleAttackingTriggers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (c.getController().isHuman()) {
|
|
||||||
AllZone.getInputControl().setInput(
|
|
||||||
new InputPayManaCostAbility(c + " - Pay to Attack\r\n", ability.getManaCost(), paidCommand,
|
|
||||||
unpaidCommand));
|
|
||||||
} else { // computer
|
|
||||||
if (ComputerUtil.canPayCost(ability)) {
|
|
||||||
ComputerUtil.playNoStack(ability);
|
|
||||||
if (!crd.hasKeyword("Vigilance")) {
|
|
||||||
crd.tap();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO remove the below line after Propaganda occurs
|
|
||||||
// during Declare_Attackers
|
|
||||||
AllZone.getCombat().removeFromCombat(crd);
|
|
||||||
}
|
|
||||||
if (bLast) {
|
if (bLast) {
|
||||||
PhaseUtil.handleAttackingTriggers();
|
PhaseUtil.handleAttackingTriggers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final Command paidCommand = new Command() {
|
||||||
|
private static final long serialVersionUID = -8303368287601871955L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
// if Propaganda is paid, tap this card
|
||||||
|
if (!crd.hasKeyword("Vigilance")) {
|
||||||
|
crd.tap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bLast) {
|
||||||
|
PhaseUtil.handleAttackingTriggers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (c.getController().isHuman()) {
|
||||||
|
GameActionUtil.payCostDuringAbilityResolve(ability, attackCost, paidCommand, unpaidCommand, null);
|
||||||
|
} else { // computer
|
||||||
|
if (ComputerUtil.canPayCost(ability)) {
|
||||||
|
ComputerUtil.playNoStack(ability);
|
||||||
|
if (!crd.hasKeyword("Vigilance")) {
|
||||||
|
crd.tap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO remove the below line after Propaganda occurs
|
||||||
|
// during Declare_Attackers
|
||||||
|
AllZone.getCombat().removeFromCombat(crd);
|
||||||
|
}
|
||||||
|
if (bLast) {
|
||||||
|
PhaseUtil.handleAttackingTriggers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user