mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
- Added the static ability "CantBlockUnless".
- Added Cowed by Wisdom.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -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/covetous_dragon.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/crab_umbra.txt svneol=native#text/plain
|
||||
res/cardsfolder/c/crabapple_cohort.txt svneol=native#text/plain
|
||||
|
||||
11
res/cardsfolder/c/cowed_by_wisdom.txt
Normal file
11
res/cardsfolder/c/cowed_by_wisdom.txt
Normal 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
|
||||
@@ -467,7 +467,7 @@ public class StaticAbility {
|
||||
}
|
||||
|
||||
if (mode.equals("CantBlockUnless")) {
|
||||
return StaticAbilityCantAttackBlock.applyCantBlockUnlessAbility(this, card);
|
||||
return StaticAbilityCantAttackBlock.applyCantBlockUnlessAbility(this, card, target);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -94,20 +94,31 @@ public class StaticAbilityCantAttackBlock {
|
||||
*
|
||||
* @param stAb
|
||||
* a StaticAbility
|
||||
* @param card
|
||||
* @param blocker
|
||||
* the card
|
||||
* @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 Card hostCard = stAb.getHostCard();
|
||||
|
||||
if (params.containsKey("ValidCard")
|
||||
&& !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
|
||||
&& !blocker.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -471,6 +471,38 @@ public class Combat {
|
||||
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>
|
||||
* getAllBlockers.
|
||||
@@ -615,34 +647,13 @@ public class Combat {
|
||||
this.blockerMap.remove(c);
|
||||
for (Card a : attackers) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // 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>
|
||||
* verifyCreaturesInPlay.
|
||||
@@ -671,7 +682,7 @@ public class Combat {
|
||||
for (final Card attacker : attacking) {
|
||||
final List<Card> block = this.getBlockers(attacker);
|
||||
|
||||
if (block.size() == 0) {
|
||||
if (block.isEmpty()) {
|
||||
// this damage is assigned to a player by setPlayerDamage()
|
||||
this.addUnblockedAttacker(attacker);
|
||||
|
||||
|
||||
@@ -27,8 +27,16 @@ import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.CardPredicates.Presets;
|
||||
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.game.GameActionUtil;
|
||||
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.zone.ZoneType;
|
||||
import forge.gui.match.CMatchUI;
|
||||
@@ -195,25 +203,59 @@ public class PhaseUtil {
|
||||
* @param 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
|
||||
// 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) {
|
||||
if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isBlocking()) {
|
||||
if (game.getCombat().getAllBlockers().size() < 2) {
|
||||
game.getCombat().undoBlockingAssignment(c);
|
||||
if (combat.getAllBlockers().size() < 2) {
|
||||
combat.undoBlockingAssignment(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
game.getStack().freezeStack();
|
||||
|
||||
game.getCombat().setUnblocked();
|
||||
combat.setUnblocked();
|
||||
|
||||
List<Card> list = new ArrayList<Card>();
|
||||
list.addAll(game.getCombat().getAllBlockers());
|
||||
list.addAll(combat.getAllBlockers());
|
||||
|
||||
list = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
@@ -222,12 +264,12 @@ public class PhaseUtil {
|
||||
}
|
||||
});
|
||||
|
||||
final List<Card> attList = game.getCombat().getAttackers();
|
||||
final List<Card> attList = combat.getAttackers();
|
||||
|
||||
CombatUtil.checkDeclareBlockers(list);
|
||||
|
||||
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) {
|
||||
CombatUtil.checkBlockedAttackers(a, b);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user