mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
- Added War Cadence
- new preference for enabling/disabling the prompt for block costs of 0.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -12542,6 +12542,7 @@ res/cardsfolder/w/wanderwine_hub.txt svneol=native#text/plain
|
||||
res/cardsfolder/w/wanderwine_prophets.txt svneol=native#text/plain
|
||||
res/cardsfolder/w/waning_wurm.txt svneol=native#text/plain
|
||||
res/cardsfolder/w/war_barge.txt -text svneol=unset#text/plain
|
||||
res/cardsfolder/w/war_cadence.txt -text
|
||||
res/cardsfolder/w/war_chariot.txt svneol=native#text/plain
|
||||
res/cardsfolder/w/war_dance.txt svneol=native#text/plain
|
||||
res/cardsfolder/w/war_elemental.txt -text
|
||||
|
||||
13
res/cardsfolder/w/war_cadence.txt
Normal file
13
res/cardsfolder/w/war_cadence.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:War Cadence
|
||||
ManaCost:2 R
|
||||
Types:Enchantment
|
||||
A:AB$ StoreSVar | Cost$ X R | SVar$ PaidNum | Type$ Count | Expression$ xPaid | SubAbility$ CadenceEffect | AILogic$ RestrictBlocking | SpellDescription$ This turn, creatures can't block unless their controller pays X for each blocking creature he or she controls.
|
||||
SVar:CadenceEffect:DB$ Effect | StaticAbilities$ CadenceStaticAb | SVars$ PaidNum | Stackable$ False | RememberObjects$ Valid Creature.blocking
|
||||
SVar:CadenceStaticAb:Mode$ CantBlockUnless | ValidCard$ Card.IsNotRemembered | Cost$ PaidNum | References$ PaidNum | EffectZone$ Command | Description$ This turn, creatures can't block unless their controller pays X for each blocking creature he or she controls.
|
||||
# According to the 10/4/2004 ruling: The ability only applies to blocks declared after it resolves. It will not add costs to any blockers already announced.
|
||||
SVar:X:Count$xPaid
|
||||
SVar:PaidNum:Number$0
|
||||
SVar:NonStackingEffect:True
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/war_cadence.jpg
|
||||
Oracle:{X}{R}: This turn, creatures can't block unless their controller pays {X} for each blocking creature he or she controls.
|
||||
@@ -1,10 +1,21 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.CardPredicates.Presets;
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.Game;
|
||||
import forge.game.ai.ComputerUtil;
|
||||
import forge.game.ai.ComputerUtilCombat;
|
||||
import forge.game.ai.ComputerUtilMana;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class StoreSVarAi extends SpellAbilityAi {
|
||||
@@ -14,7 +25,50 @@ public class StoreSVarAi extends SpellAbilityAi {
|
||||
//Tree of Redemption
|
||||
|
||||
final Card source = sa.getSourceCard();
|
||||
if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|
||||
final Game game = ai.getGame();
|
||||
final Combat combat = game.getCombat();
|
||||
final PhaseHandler ph = game.getPhaseHandler();
|
||||
final Player opp = ai.getOpponents().get(0);
|
||||
|
||||
if (sa.hasParam("AILogic")) {
|
||||
if (sa.getPayCosts().getTotalMana().countX() > 0 && source.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to half the remaining mana to allow for Main 2 and other combat shenanigans.
|
||||
final int xPay = ComputerUtilMana.determineLeftoverMana(sa, ai) / 2;
|
||||
if (xPay == 0) { return false; }
|
||||
source.setSVar("PayX", Integer.toString(xPay));
|
||||
}
|
||||
|
||||
final String logic = sa.getParam("AILogic");
|
||||
if (logic.equals("RestrictBlocking")) {
|
||||
if (!ph.isPlayerTurn(ai) || ph.getPhase().isBefore(PhaseType.COMBAT_BEGIN)
|
||||
|| ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Card> possibleAttackers = ai.getCreaturesInPlay();
|
||||
List<Card> possibleBlockers = opp.getCreaturesInPlay();
|
||||
possibleBlockers = CardLists.filter(possibleBlockers, Presets.UNTAPPED);
|
||||
int oppLife = opp.getLife();
|
||||
int potentialDmg = 0;
|
||||
List<Card> currentAttackers = new ArrayList<Card>();
|
||||
|
||||
if (possibleBlockers.size() == 0) { return false; }
|
||||
|
||||
for (final Card creat : possibleAttackers) {
|
||||
if (CombatUtil.canAttack(creat, opp) && possibleBlockers.size() > 1) {
|
||||
potentialDmg += creat.getCurrentPower();
|
||||
if (potentialDmg >= oppLife) { return true; }
|
||||
}
|
||||
if (combat != null && combat.isAttacking(creat)) {
|
||||
currentAttackers.add(creat);
|
||||
}
|
||||
}
|
||||
|
||||
return currentAttackers.size() > possibleBlockers.size();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|
||||
|| (ai.getLife() > 5 && !ComputerUtilCombat.lifeInSeriousDanger(ai, ai.getGame().getCombat()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -664,19 +664,25 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
|
||||
private static boolean payRequiredBlockCosts(Game game, Card blocker, Card attacker) {
|
||||
Cost blockCost = new Cost(ManaCost.ZERO, true);
|
||||
boolean hasBlockCost = false;
|
||||
// Sort abilities to apply them in proper order
|
||||
for (Card card : game.getCardsIn(ZoneType.Battlefield)) {
|
||||
List<ZoneType> checkZones = ZoneType.listValueOf("Battlefield,Command");
|
||||
for (Card card : game.getCardsIn(checkZones)) {
|
||||
final ArrayList<StaticAbility> staticAbilities = card.getStaticAbilities();
|
||||
for (final StaticAbility stAb : staticAbilities) {
|
||||
Cost c1 = stAb.getBlockCost(blocker, attacker);
|
||||
if ( c1 != null )
|
||||
if ( c1 != null ) {
|
||||
blockCost.add(c1);
|
||||
hasBlockCost = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasPaid = blockCost.getTotalMana().isZero() && blockCost.isOnlyManaCost(); // true if needless to pay
|
||||
|
||||
boolean hasPaid = blockCost.getTotalMana().isZero() && blockCost.isOnlyManaCost() && (!hasBlockCost
|
||||
|| Singletons.getModel().getPreferences().getPrefBoolean(FPref.MATCHPREF_PROMPT_FREE_BLOCKS)); // true if needless to pay
|
||||
|
||||
if (!hasPaid) {
|
||||
hasPaid = blocker.getController().getController().payManaOptional(blocker, blockCost, null, "Pay cost to declare " + blocker + " a blocker", ManaPaymentPurpose.DeclareBlocker);
|
||||
hasPaid = blocker.getController().getController().payManaOptional(blocker, blockCost, null, "Pay cost to declare " + blocker + " a blocker. ", ManaPaymentPurpose.DeclareBlocker);
|
||||
}
|
||||
return hasPaid;
|
||||
}
|
||||
|
||||
@@ -302,10 +302,16 @@ public class HumanPlay {
|
||||
costPart = parts.get(0);
|
||||
}
|
||||
final String orString = prompt != null ? "" : " (or: " + sourceAbility.getStackDescription() + ")";
|
||||
|
||||
|
||||
if (parts.isEmpty() || costPart.getAmount().equals("0")) {
|
||||
return GuiDialog.confirm(source, "Do you want to pay 0?" + orString);
|
||||
}
|
||||
// 0 mana costs were slipping through because CostPart.getAmount returns 1
|
||||
else if (costPart instanceof CostPartMana ) {
|
||||
if (((CostPartMana) costPart).getManaToPay().isZero()) {
|
||||
return GuiDialog.confirm(source, "Do you want to pay 0?" + orString);
|
||||
}
|
||||
}
|
||||
|
||||
//the following costs do not need inputs
|
||||
for (CostPart part : parts) {
|
||||
|
||||
@@ -86,6 +86,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
lstControls.add(Pair.of(view.getCbOverlayCardManaCost(), FPref.UI_OVERLAY_CARD_MANA_COST));
|
||||
lstControls.add(Pair.of(view.getCbShowMatchBackgroundImage(), FPref.UI_MATCH_IMAGE_VISIBLE));
|
||||
lstControls.add(Pair.of(view.getCbUseThemedComboBox(), FPref.UI_THEMED_COMBOBOX));
|
||||
lstControls.add(Pair.of(view.getCbPromptFreeBlocks(), FPref.MATCHPREF_PROMPT_FREE_BLOCKS));
|
||||
|
||||
for(final Pair<JCheckBox, FPref> kv : lstControls) {
|
||||
kv.getKey().addItemListener(new ItemListener() {
|
||||
|
||||
@@ -81,8 +81,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
private final JCheckBox cbOverlayCardPower = new OptionsCheckBox("Power/Toughness");
|
||||
private final JCheckBox cbOverlayCardManaCost = new OptionsCheckBox("Mana Cost");
|
||||
private final JCheckBox cbCompactMainMenu = new OptionsCheckBox("Use Compact Main Sidebar Menu");
|
||||
private final JCheckBox cbShowMatchBackgroundImage = new OptionsCheckBox("Show Background Image on Match Screen");
|
||||
private final JCheckBox cbShowMatchBackgroundImage = new OptionsCheckBox("Show Background Image on Match Screen");
|
||||
private final JCheckBox cbUseThemedComboBox = new OptionsCheckBox("Themed ComboBox");
|
||||
private final JCheckBox cbPromptFreeBlocks = new OptionsCheckBox("Free Block Handling");
|
||||
|
||||
private final Map<FPref, KeyboardShortcutField> shortcutFields = new HashMap<FPref, KeyboardShortcutField>();
|
||||
|
||||
@@ -146,7 +147,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
|
||||
pnlPrefs.add(cbCloneImgSource, regularConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled clones will use their original art instead of the cloned card's art"), regularConstraints);
|
||||
|
||||
|
||||
pnlPrefs.add(cbPromptFreeBlocks, regularConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, if you would have to pay 0 to block, pay automatically without prompt"), regularConstraints);
|
||||
|
||||
// Deck building options
|
||||
pnlPrefs.add(new SectionLabel("Random Deck Generation"), sectionConstraints);
|
||||
|
||||
@@ -489,6 +493,11 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
return cbCloneImgSource;
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JCheckBox} */
|
||||
public JCheckBox getCbPromptFreeBlocks() {
|
||||
return cbPromptFreeBlocks;
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JCheckBox} */
|
||||
public JCheckBox getCbEnableSounds() {
|
||||
return cbEnableSounds;
|
||||
|
||||
@@ -64,6 +64,8 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
|
||||
UI_FOR_TOUCHSCREN("false"),
|
||||
|
||||
MATCHPREF_PROMPT_FREE_BLOCKS("false"),
|
||||
|
||||
SUBMENU_CURRENTMENU (EMenuItem.CONSTRUCTED.toString()),
|
||||
SUBMENU_SANCTIONED ("true"),
|
||||
SUBMENU_GAUNTLET ("false"),
|
||||
|
||||
Reference in New Issue
Block a user