- Added the static ability "CantBlockUnless".

- Added Cowed by Wisdom.
This commit is contained in:
Sloth
2013-04-14 14:01:27 +00:00
parent f214be71bf
commit 6502684f3c
6 changed files with 112 additions and 36 deletions

1
.gitattributes vendored
View File

@@ -2064,6 +2064,7 @@ res/cardsfolder/c/cover_of_darkness.txt svneol=native#text/plain
res/cardsfolder/c/covert_operative.txt svneol=native#text/plain res/cardsfolder/c/covert_operative.txt svneol=native#text/plain
res/cardsfolder/c/covetous_dragon.txt svneol=native#text/plain res/cardsfolder/c/covetous_dragon.txt svneol=native#text/plain
res/cardsfolder/c/cowardice.txt svneol=native#text/plain res/cardsfolder/c/cowardice.txt svneol=native#text/plain
res/cardsfolder/c/cowed_by_wisdom.txt -text
res/cardsfolder/c/cower_in_fear.txt -text res/cardsfolder/c/cower_in_fear.txt -text
res/cardsfolder/c/crab_umbra.txt svneol=native#text/plain res/cardsfolder/c/crab_umbra.txt svneol=native#text/plain
res/cardsfolder/c/crabapple_cohort.txt svneol=native#text/plain res/cardsfolder/c/crabapple_cohort.txt svneol=native#text/plain

View File

@@ -0,0 +1,11 @@
Name:Cowed by Wisdom
ManaCost:W
Types:Enchantment Aura
K:Enchant creature
A:SP$ Attach | Cost$ W | ValidTgts$ Creature | AILogic$ Curse
S:Mode$ CantAttackUnless | ValidCard$ Creature.AttachedBy | Cost$ X | Description$ Enchanted creature can't attack or block unless its controller pays {1} for each card in your hand.
S:Mode$ CantBlockUnless | ValidCard$ Creature.AttachedBy | Cost$ X
SVar:X:Count$InYourHand
SVar:Picture:http://www.wizards.com/global/images/magic/general/cowed_by_wisdom.jpg
Oracle:Enchant creature\nEnchanted creature can't attack or block unless its controller pays {1} for each card in your hand.
SetInfo:SOK Common

View File

@@ -467,7 +467,7 @@ public class StaticAbility {
} }
if (mode.equals("CantBlockUnless")) { if (mode.equals("CantBlockUnless")) {
return StaticAbilityCantAttackBlock.applyCantBlockUnlessAbility(this, card); return StaticAbilityCantAttackBlock.applyCantBlockUnlessAbility(this, card, target);
} }
return null; return null;

View File

@@ -94,20 +94,31 @@ public class StaticAbilityCantAttackBlock {
* *
* @param stAb * @param stAb
* a StaticAbility * a StaticAbility
* @param card * @param blocker
* the card * the card
* @return a Cost * @return a Cost
*/ */
public static Cost applyCantBlockUnlessAbility(final StaticAbility stAb, final Card card) { public static Cost applyCantBlockUnlessAbility(final StaticAbility stAb, final Card blocker, final GameEntity attacker) {
final HashMap<String, String> params = stAb.getMapParams(); final HashMap<String, String> params = stAb.getMapParams();
final Card hostCard = stAb.getHostCard(); final Card hostCard = stAb.getHostCard();
if (params.containsKey("ValidCard") if (params.containsKey("ValidCard")
&& !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) { && !blocker.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
return null; return null;
} }
final Cost cost = new Cost(hostCard, params.get("Cost"), true); if (params.containsKey("Attacker") && attacker != null
&& !attacker.isValid(params.get("Attacker").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; return cost;
} }

View File

@@ -471,6 +471,38 @@ public class Combat {
Singletons.getModel().getGame().getEvents().post(new BlockerAssignedEvent()); Singletons.getModel().getGame().getEvents().post(new BlockerAssignedEvent());
} }
public final void removeBlockAssignment(final Card attacker, final Card blocker) {
this.attackerMap.get(attacker).remove(blocker);
this.blockerMap.get(blocker).remove(attacker);
if (this.attackerMap.get(attacker).isEmpty()) {
this.blocked.remove(attacker);
}
if (this.blockerMap.get(blocker).isEmpty()) {
this.blockerMap.remove(blocker);
}
}
/**
* <p>
* undoBlockingAssignment.
* </p>
*
* @param blocker
* a {@link forge.Card} object.
*/
public final void undoBlockingAssignment(final Card blocker) {
final List<Card> att = this.getAttackers();
for (final Card attacker : att) {
if (this.getBlockers(attacker).contains(blocker)) {
this.getBlockingAttackerList(attacker).remove(blocker);
if (this.getBlockers(attacker).isEmpty()) {
this.blocked.remove(attacker);
}
}
}
this.blockerMap.remove(blocker);
} // undoBlockingAssignment(Card)
/** /**
* <p> * <p>
* getAllBlockers. * getAllBlockers.
@@ -615,34 +647,13 @@ public class Combat {
this.blockerMap.remove(c); this.blockerMap.remove(c);
for (Card a : attackers) { for (Card a : attackers) {
this.attackerMap.get(a).remove(c); this.attackerMap.get(a).remove(c);
if (stillDeclaring && this.attackerMap.get(a).size() == 0) { if (stillDeclaring && this.attackerMap.get(a).isEmpty()) {
this.blocked.remove(a); this.blocked.remove(a);
} }
} }
} }
} // removeFromCombat() } // removeFromCombat()
/**
* <p>
* undoBlockingAssignment.
* </p>
*
* @param blocker
* a {@link forge.Card} object.
*/
public final void undoBlockingAssignment(final Card blocker) {
final List<Card> att = this.getAttackers();
for (final Card attacker : att) {
if (this.getBlockers(attacker).contains(blocker)) {
this.getBlockingAttackerList(attacker).remove(blocker);
if (this.getBlockers(attacker).size() == 0) {
this.blocked.remove(attacker);
}
}
}
this.blockerMap.remove(blocker);
} // undoBlockingAssignment(Card)
/** /**
* <p> * <p>
* verifyCreaturesInPlay. * verifyCreaturesInPlay.
@@ -671,7 +682,7 @@ public class Combat {
for (final Card attacker : attacking) { for (final Card attacker : attacking) {
final List<Card> block = this.getBlockers(attacker); final List<Card> block = this.getBlockers(attacker);
if (block.size() == 0) { if (block.isEmpty()) {
// this damage is assigned to a player by setPlayerDamage() // this damage is assigned to a player by setPlayerDamage()
this.addUnblockedAttacker(attacker); this.addUnblockedAttacker(attacker);

View File

@@ -27,8 +27,16 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.Singletons; import forge.Singletons;
import forge.card.cost.Cost;
import forge.card.spellability.Ability;
import forge.card.spellability.AbilityStatic;
import forge.card.staticability.StaticAbility;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.GameActionUtil;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCost;
import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
@@ -195,25 +203,59 @@ public class PhaseUtil {
* @param game * @param game
*/ */
public static void handleDeclareBlockers(GameState game) { public static void handleDeclareBlockers(GameState game) {
game.getCombat().verifyCreaturesInPlay(); final Combat combat = game.getCombat();
combat.verifyCreaturesInPlay();
// Handles removing cards like Mogg Flunkies from combat if group block // Handles removing cards like Mogg Flunkies from combat if group block
// didn't occur // didn't occur
final List<Card> filterList = game.getCombat().getAllBlockers(); final List<Card> filterList = combat.getAllBlockers();
for (Card blocker : filterList) {
final List<Card> attackers = new ArrayList<Card>(combat.getAttackersBlockedBy(blocker));
for (Card attacker : attackers) {
Cost blockCost = new Cost(blocker, "0", true);
// Sort abilities to apply them in proper order
for (Card card : game.getCardsIn(ZoneType.Battlefield)) {
final ArrayList<StaticAbility> staticAbilities = card.getStaticAbilities();
for (final StaticAbility stAb : staticAbilities) {
Cost additionalCost = stAb.getCostAbility("CantBlockUnless", blocker, attacker);
blockCost = Cost.combine(blockCost, additionalCost);
}
}
boolean hasPaid = blockCost.getTotalMana().isZero() && blockCost.isOnlyManaCost(); // true if needless to pay
if (!hasPaid) {
final Ability ability = new AbilityStatic(blocker, blockCost, null) { @Override public void resolve() {} };
ability.setActivatingPlayer(blocker.getController());
if (blocker.getController().isHuman()) {
hasPaid = GameActionUtil.payCostDuringAbilityResolve(ability, blockCost, null, game);
} else { // computer
if (ComputerUtilCost.canPayCost(ability, blocker.getController())) {
ComputerUtil.playNoStack((AIPlayer)blocker.getController(), ability, game);
hasPaid = true;
}
}
}
if ( !hasPaid ) {
combat.removeBlockAssignment(attacker, blocker);
}
}
}
for (Card c : filterList) { for (Card c : filterList) {
if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isBlocking()) { if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isBlocking()) {
if (game.getCombat().getAllBlockers().size() < 2) { if (combat.getAllBlockers().size() < 2) {
game.getCombat().undoBlockingAssignment(c); combat.undoBlockingAssignment(c);
} }
} }
} }
game.getStack().freezeStack(); game.getStack().freezeStack();
game.getCombat().setUnblocked(); combat.setUnblocked();
List<Card> list = new ArrayList<Card>(); List<Card> list = new ArrayList<Card>();
list.addAll(game.getCombat().getAllBlockers()); list.addAll(combat.getAllBlockers());
list = CardLists.filter(list, new Predicate<Card>() { list = CardLists.filter(list, new Predicate<Card>() {
@Override @Override
@@ -222,12 +264,12 @@ public class PhaseUtil {
} }
}); });
final List<Card> attList = game.getCombat().getAttackers(); final List<Card> attList = combat.getAttackers();
CombatUtil.checkDeclareBlockers(list); CombatUtil.checkDeclareBlockers(list);
for (final Card a : attList) { for (final Card a : attList) {
final List<Card> blockList = game.getCombat().getBlockers(a); final List<Card> blockList = combat.getBlockers(a);
for (final Card b : blockList) { for (final Card b : blockList) {
CombatUtil.checkBlockedAttackers(a, b); CombatUtil.checkBlockedAttackers(a, b);
} }