mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Merge branch 'master' into Attractions
This commit is contained in:
@@ -485,7 +485,7 @@ public class DamageDealAi extends DamageAiBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
return damageChoosingTargets(ai, saMe, tgt, dmg, false, immediately);
|
||||
return damageChoosingTargets(ai, saMe, tgt, dmg, saMe.isMandatory(), immediately);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -174,6 +174,21 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
return cp != null && !cp.isEmpty();
|
||||
}
|
||||
|
||||
public PaperCard removeCardName(String name) {
|
||||
PaperCard paperCard;
|
||||
for (Entry<DeckSection, CardPool> kv : parts.entrySet()) {
|
||||
CardPool pool = kv.getValue();
|
||||
for (Entry<PaperCard, Integer> pc : pool) {
|
||||
if (pc.getKey().getName().equalsIgnoreCase(name)) {
|
||||
paperCard = pc.getKey();
|
||||
pool.remove(paperCard);
|
||||
return paperCard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// will return new if it was absent
|
||||
public CardPool getOrCreate(DeckSection deckSection) {
|
||||
CardPool p = get(deckSection);
|
||||
|
||||
@@ -22,10 +22,7 @@ package forge.game;
|
||||
*/
|
||||
public enum GlobalRuleChange {
|
||||
|
||||
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."),
|
||||
onlyOneBlocker ("No more than one creature can block each combat."),
|
||||
onlyOneBlockerPerOpponent ("Each opponent can't block with more than one creature."),
|
||||
onlyTwoBlockers ("No more than two creatures can block each combat.");
|
||||
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat.");
|
||||
|
||||
private final String ruleText;
|
||||
|
||||
|
||||
@@ -2133,6 +2133,9 @@ public class CardProperty {
|
||||
List<String> nameList = Lists.newArrayList(names.split(";"));
|
||||
|
||||
return nameList.contains(card.getName());
|
||||
} else if (property.equals("NotedGuessPhantasm")) {
|
||||
String names = sourceController.getDraftNotes().get("Spire Phantasm");
|
||||
return names != null && !names.isEmpty();
|
||||
} else if (property.equals("NotedTypes")) {
|
||||
// Should Paliano Vanguard be hardcoded here or part of the property?
|
||||
String types = sourceController.getDraftNotes().get("Paliano Vanguard");
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.google.common.collect.Lists;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -36,6 +35,7 @@ import forge.game.player.Player;
|
||||
import forge.game.player.PlayerController.ManaPaymentPurpose;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.staticability.StaticAbilityBlockRestrict;
|
||||
import forge.game.staticability.StaticAbilityCantAttackBlock;
|
||||
import forge.game.staticability.StaticAbilityMustBlock;
|
||||
import forge.game.trigger.TriggerType;
|
||||
@@ -457,21 +457,11 @@ public class CombatUtil {
|
||||
if (!canBlockMoreCreatures(blocker, combat.getAttackersBlockedBy(blocker))) {
|
||||
return false;
|
||||
}
|
||||
final Game game = blocker.getGame();
|
||||
final int blockers = combat.getAllBlockers().size();
|
||||
|
||||
if (blockers > 1 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyTwoBlockers)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blockers > 0 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneBlocker)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CardCollection allOtherBlockers = combat.getAllBlockers();
|
||||
allOtherBlockers.remove(blocker);
|
||||
final int blockersFromOnePlayer = CardLists.count(allOtherBlockers, CardPredicates.isController(blocker.getController()));
|
||||
if (blockersFromOnePlayer > 0 && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.onlyOneBlockerPerOpponent)) {
|
||||
if (blockersFromOnePlayer >= StaticAbilityBlockRestrict.blockRestrictNum(blocker.getController())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2134,12 +2134,8 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
return lost;
|
||||
}
|
||||
|
||||
public final boolean hasProwl(final Set<String> types) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String type : types) {
|
||||
sb.append("Card.YouCtrl+").append(type).append(",");
|
||||
}
|
||||
return !game.getDamageDoneThisTurn(true, true, sb.toString(), "Player", null, this, null).isEmpty();
|
||||
public final boolean hasProwl(final SpellAbility sa) {
|
||||
return !game.getDamageDoneThisTurn(true, true, "Card.YouCtrl+sharesCreatureTypeWith", "Player", sa.getHostCard(), this, sa).isEmpty();
|
||||
}
|
||||
|
||||
public final boolean hasFreerunning() {
|
||||
|
||||
@@ -440,7 +440,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
}
|
||||
}
|
||||
if (sa.isProwl()) {
|
||||
if (!activator.hasProwl(c.getType().getCreatureTypes())) {
|
||||
if (!activator.hasProwl(sa)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package forge.game.staticability;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class StaticAbilityBlockRestrict {
|
||||
static String MODE = "BlockRestrict";
|
||||
|
||||
static public int blockRestrictNum(Player defender) {
|
||||
final Game game = defender.getGame();
|
||||
int num = Integer.MAX_VALUE;
|
||||
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
|
||||
for (final StaticAbility stAb : ca.getStaticAbilities()) {
|
||||
if (!stAb.checkConditions(MODE)) {
|
||||
continue;
|
||||
}
|
||||
if (blockRestrict(stAb, defender)) {
|
||||
int stNum = AbilityUtils.calculateAmount(stAb.getHostCard(),
|
||||
stAb.getParamOrDefault("MaxBlockers", "1"), stAb);
|
||||
if (stNum < num) {
|
||||
num = stNum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static public boolean blockRestrict(StaticAbility stAb, Player defender) {
|
||||
if (!stAb.matchesValidParam("ValidDefender", defender)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -116,12 +116,21 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> i
|
||||
// can only draft one at a time, regardless of the requested quantity
|
||||
PaperCard card = items.iterator().next().getKey();
|
||||
|
||||
if (boosterDraft.getHumanPlayer().shouldSkipThisPick()) {
|
||||
System.out.println(card + " not drafted because we're skipping this pick");
|
||||
showPackToDraft();
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify if card is in the activate pack?
|
||||
this.getDeckManager().addItem(card, 1);
|
||||
|
||||
// get next booster pack
|
||||
// get next booster pack if we aren't picking again from this pack
|
||||
this.boosterDraft.setChoice(card);
|
||||
showPackToDraft();
|
||||
}
|
||||
|
||||
protected void showPackToDraft() {
|
||||
boolean nextChoice = this.boosterDraft.hasNextChoice();
|
||||
ItemPool<PaperCard> pool = null;
|
||||
if (nextChoice) {
|
||||
|
||||
@@ -58,10 +58,15 @@ public class BoosterDraftTest implements IBoosterDraft {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setChoice(final PaperCard c) {
|
||||
public boolean setChoice(final PaperCard c) {
|
||||
System.out.println(c.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -132,3 +132,4 @@ Alchemy: Ixalan, 3/6/LCI, YLCI
|
||||
Ravnica Remastered, 3/6/RAV, RVR
|
||||
Murders at Karlov Manor, 3/6/MKM, MKM
|
||||
Outlaws of Thunder Junction, 3/6/OTJ, OTJ
|
||||
Modern Horizons 3, 3/6/MH3, MH3
|
||||
7
forge-gui/res/cardsfolder/a/agent_of_acquisitions.txt
Normal file
7
forge-gui/res/cardsfolder/a/agent_of_acquisitions.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Name:Agent of Acquisitions
|
||||
ManaCost:2
|
||||
Types:Artifact Creature Construct
|
||||
PT:2/1
|
||||
Draft:Draft CARDNAME face up.
|
||||
Draft:Instead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn CARDNAME face down and you can’t draft cards for the rest of this draft round. (You may look at booster packs passed to you.)
|
||||
Oracle:Draft Agent of Acquisitions face up.\nInstead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn Agent of Acquisitions face down and you can’t draft cards for the rest of this draft round. (You may look at booster packs passed to you.)
|
||||
@@ -4,6 +4,6 @@ Types:Creature Human
|
||||
PT:3/1
|
||||
K:Squad:2
|
||||
K:CARDNAME can't block.
|
||||
A:AB$ Pump | PrecostDesc$ Endurant — | Cost$ PayLife<3> | KW$ Indestructible | SpellDescription$ CARDNAME gains indestructible until end of turn.
|
||||
A:AB$ Pump | PrecostDesc$ Endurant — | Cost$ PayLife<3> | KW$ Indestructible | Defined$ Self | SpellDescription$ CARDNAME gains indestructible until end of turn.
|
||||
DeckHas:Ability$Token
|
||||
Oracle:Squad {2} (As an additional cost to cast this spell, you may pay {2} any number of times. When this creature enters the battlefield, create that many tokens that are copies of it.)\nArco-Flagellant can't block.\nEndurant — Pay 3 life: Arco-Flagellant gains indestructible until end of turn.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Astral Arena
|
||||
ManaCost:no cost
|
||||
Types:Plane Kolbahan
|
||||
S:Mode$ AttackRestrict | EffectZone$ Command | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
|
||||
S:Mode$ Continuous | EffectZone$ Command | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
|
||||
S:Mode$ BlockRestrict | EffectZone$ Command | MaxBlockers$ 1 | Description$ No more than one creature can block each combat.
|
||||
T:Mode$ ChaosEnsues | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever chaos ensues, CARDNAME deals 2 damage to each creature.
|
||||
SVar:RolledChaos:DB$ DamageAll | NumDmg$ 2 | ValidCards$ Creature
|
||||
SVar:AIRollPlanarDieParams:Mode$ Random | MinTurn$ 5
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Elemental Knight
|
||||
PT:5/6
|
||||
K:Reach
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, reveal the top five cards of your library. Put a land card from among them onto the battlefield and the rest into your graveyard.
|
||||
SVar:TrigDig:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | ChangeValid$ Land | Optional$ True | DestinationZone$ Battlefield | DestinationZone2$ Graveyard
|
||||
SVar:TrigDig:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | ChangeValid$ Land | DestinationZone$ Battlefield | DestinationZone2$ Graveyard
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, put another target card from your graveyard on top of your library.
|
||||
SVar:TrigExile:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Graveyard | Destination$ Library | ValidTgts$ Card.YouOwn+Other | TgtPrompt$ Select another target card from your graveyard | AITgts$ Card.Other
|
||||
DeckHas:Ability$Graveyard
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Caverns of Despair
|
||||
ManaCost:2 R R
|
||||
Types:World Enchantment
|
||||
S:Mode$ AttackRestrict | MaxAttackers$ 2 | Description$ No more than two creatures can attack each combat.
|
||||
S:Mode$ Continuous | GlobalRule$ No more than two creatures can block each combat. | Description$ No more than two creatures can block each combat.
|
||||
S:Mode$ BlockRestrict | MaxBlockers$ 2 | Description$ No more than two creatures can block each combat.
|
||||
SVar:NonStackingEffect:True
|
||||
AI:RemoveDeck:Random
|
||||
DeckHints:Type$Planeswalker|Artifact|Enchantment|Aura|Equipment
|
||||
|
||||
7
forge-gui/res/cardsfolder/c/cogwork_librarian.txt
Normal file
7
forge-gui/res/cardsfolder/c/cogwork_librarian.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Name:Cogwork Librarian
|
||||
ManaCost:4
|
||||
Types:Artifact Creature Construct
|
||||
PT:3/3
|
||||
Draft:Draft CARDNAME face up.
|
||||
Draft:As you draft a card, you may draft an additional card from that booster pack. If you do, put CARDNAME into that booster pack.
|
||||
Oracle:Draft Cogwork Librarian face up.\nAs you draft a card, you may draft an additional card from that booster pack. If you do, put Cogwork Librarian into that booster pack.
|
||||
@@ -2,6 +2,6 @@ Name:Dueling Grounds
|
||||
ManaCost:1 G W
|
||||
Types:Enchantment
|
||||
S:Mode$ AttackRestrict | MaxAttackers$ 1 | Description$ No more than one creature can attack each combat.
|
||||
S:Mode$ Continuous | GlobalRule$ No more than one creature can block each combat. | Description$ No more than one creature can block each combat.
|
||||
S:Mode$ BlockRestrict | MaxBlockers$ 1 | Description$ No more than one creature can block each combat.
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:No more than one creature can attack each combat.\nNo more than one creature can block each combat.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user