- !PrintSheets can now be referenced inside Booster contents of an edition file

- M15 Boosters no longer contain cards only found in Intro decks
- Adding a few Conspiracy type cards, along with the capability of their use (NOTE: Deck editors still need a way to add Conspiracy types)
- Added Brago's Favor, Immediate Action, Muzzio's Preparations, Secret Summoning, Secrets of Paradise
This commit is contained in:
Sol
2014-07-21 02:56:13 +00:00
parent 007ebc3e9c
commit c42f6fea9d
22 changed files with 193 additions and 8 deletions

5
.gitattributes vendored
View File

@@ -2635,6 +2635,7 @@ forge-gui/res/cardsfolder/b/bower_passage.txt -text
forge-gui/res/cardsfolder/b/brace_for_impact.txt -text
forge-gui/res/cardsfolder/b/brackwater_elemental.txt svneol=native#text/plain
forge-gui/res/cardsfolder/b/brago_king_eternal.txt -text
forge-gui/res/cardsfolder/b/bragos_favor.txt -text
forge-gui/res/cardsfolder/b/bragos_representative.txt -text
forge-gui/res/cardsfolder/b/braid_of_fire.txt svneol=native#text/plain
forge-gui/res/cardsfolder/b/braids_cabal_minion.txt svneol=native#text/plain
@@ -7033,6 +7034,7 @@ forge-gui/res/cardsfolder/i/imagecrafter.txt -text
forge-gui/res/cardsfolder/i/imaginary_pet.txt svneol=native#text/plain
forge-gui/res/cardsfolder/i/imi_statue.txt svneol=native#text/plain
forge-gui/res/cardsfolder/i/immaculate_magistrate.txt svneol=native#text/plain
forge-gui/res/cardsfolder/i/immediate_action.txt -text
forge-gui/res/cardsfolder/i/immersturm.txt -text
forge-gui/res/cardsfolder/i/immerwolf.txt -text
forge-gui/res/cardsfolder/i/immobilizing_ink.txt svneol=native#text/plain
@@ -9084,6 +9086,7 @@ forge-gui/res/cardsfolder/m/mutavault.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mutilate.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mutual_epiphany.txt -text
forge-gui/res/cardsfolder/m/muzzio_visionary_architect.txt -text
forge-gui/res/cardsfolder/m/muzzios_preparations.txt -text
forge-gui/res/cardsfolder/m/muzzle.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mwonvuli_acid_moss.txt svneol=native#text/plain
forge-gui/res/cardsfolder/m/mwonvuli_beast_tracker.txt -text
@@ -11646,7 +11649,9 @@ forge-gui/res/cardsfolder/s/second_sight.txt svneol=native#text/plain
forge-gui/res/cardsfolder/s/second_sunrise.txt -text
forge-gui/res/cardsfolder/s/second_thoughts.txt svneol=native#text/plain
forge-gui/res/cardsfolder/s/second_wind.txt svneol=native#text/plain
forge-gui/res/cardsfolder/s/secret_summoning.txt -text
forge-gui/res/cardsfolder/s/secretkeeper.txt -text
forge-gui/res/cardsfolder/s/secrets_of_paradise.txt -text
forge-gui/res/cardsfolder/s/secrets_of_the_dead.txt -text
forge-gui/res/cardsfolder/s/security_blockade.txt -text
forge-gui/res/cardsfolder/s/security_detail.txt svneol=native#text/plain

View File

@@ -814,6 +814,9 @@ public class PlayerControllerAi extends PlayerController {
return ComputerUtilCard.getMostProminentCardName(player.getCardsIn(ZoneType.Library));
} else if (logic.equals("MostProminentInHumanDeck")) {
return ComputerUtilCard.getMostProminentCardName(player.getOpponent().getCardsIn(ZoneType.Library));
} else if (logic.equals("MostProminentCreatureInComputerDeck")) {
List<Card> cards = CardLists.getValidCards(player.getCardsIn(ZoneType.Library), "Creature", player, sa.getHostCard());
return ComputerUtilCard.getMostProminentCardName(cards);
} else if (logic.equals("BestCreatureInComputerDeck")) {
return ComputerUtilCard.getBestCreatureAI(player.getCardsIn(ZoneType.Library)).getName();
} else if (logic.equals("RandomInComputerDeck")) {

View File

@@ -176,8 +176,8 @@ public class BoosterGenerator {
if( invert ) operator = operator.substring(1);
Predicate<PaperCard> toAdd = null;
if( operator.equalsIgnoreCase("dfc") ) { toAdd = Predicates.compose(CardRulesPredicates.splitType(CardSplitType.Transform), PaperCard.FN_GET_RULES);
} else if ( operator.equalsIgnoreCase(BoosterSlots.LAND) ) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES);
if( operator.equalsIgnoreCase(BoosterSlots.DUAL_FACED_CARD) ) { toAdd = Predicates.compose(CardRulesPredicates.splitType(CardSplitType.Transform), PaperCard.FN_GET_RULES);
} else if ( operator.equalsIgnoreCase(BoosterSlots.LAND) ) { toAdd = Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES);
} else if ( operator.equalsIgnoreCase(BoosterSlots.BASIC_LAND)) { toAdd = IPaperCard.Predicates.Presets.IS_BASIC_LAND;
} else if ( operator.equalsIgnoreCase(BoosterSlots.TIME_SHIFTED)) { toAdd = IPaperCard.Predicates.Presets.IS_SPECIAL;
} else if ( operator.equalsIgnoreCase(BoosterSlots.MYTHIC)) { toAdd = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
@@ -188,6 +188,14 @@ public class BoosterGenerator {
operator = StringUtils.strip(operator.substring(4), "() ");
String[] cardNames = TextUtil.splitWithParenthesis(operator, ',', '"', '"');
toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames));
} else if (operator.startsWith("fromSheet(")) {
String sheetName = StringUtils.strip(operator.substring(9), "()\" ");
Iterable<PaperCard> src = StaticData.instance().getPrintSheets().get(sheetName).toFlatList();
ArrayList<String> cardNames = Lists.newArrayList();
for (PaperCard card : src) {
cardNames.add(card.getName());
}
toAdd = IPaperCard.Predicates.names(Lists.newArrayList(cardNames));
}
if(toAdd == null)

View File

@@ -11,4 +11,5 @@ public class BoosterSlots {
public static final String MYTHIC = "Mythic";
public static final String BASIC_LAND = "BasicLand";
public static final String TIME_SHIFTED = "TimeShifted";
public static final String DUAL_FACED_CARD = "dfc";
}

View File

@@ -96,7 +96,7 @@ public final class CardRules implements ICardCharacteristics {
public boolean isVariant() {
CardType t = getType();
return t.isVanguard() || t.isScheme() || t.isPlane() || t.isPhenomenon();
return t.isVanguard() || t.isScheme() || t.isPlane() || t.isPhenomenon() || t.isConspiracy();
}
public CardSplitType getSplitType() {

View File

@@ -38,6 +38,7 @@ public final class CardType implements Comparable<CardType> {
public enum CoreType {
Artifact(true),
Conspiracy(false),
Creature(true),
Enchantment(true),
Instant(false),
@@ -216,6 +217,10 @@ public final class CardType implements Comparable<CardType> {
return this.coreType.contains(CardType.CoreType.Sorcery);
}
public boolean isConspiracy() {
return this.coreType.contains(CoreType.Conspiracy);
}
public boolean isVanguard() {
return this.coreType.contains(CardType.CoreType.Vanguard);
}
@@ -346,10 +351,11 @@ public final class CardType implements Comparable<CardType> {
// types.addAll(getCardTypes());
types.addAll(Constant.CARD_TYPES);
// not currently used by Forge
// Variant card types (I don't understand these lines, shouldn't core types be enough?)
types.add("Plane");
types.add("Scheme");
types.add("Vanguard");
types.add("Conspiracy");
return types;
}

View File

@@ -114,6 +114,9 @@ public enum DeckFormat {
int min = getMainRange().getMinimum();
int max = getMainRange().getMaximum();
// TODO "Your minimum deck size is reduced by five."
// Adjust minimum base on number of Advantageous Proclamation or similar cards
if (deckSize < min) {
return String.format("should have a minimum of %d cards", min);
}

View File

@@ -6,7 +6,8 @@ public enum DeckSection {
Main(60),
Sideboard(15),
Planes(10),
Schemes(20);
Schemes(20),
Conspiracy(0);
private final int typicalSize; // Rules enforcement is done in DeckFormat class, this is for reference only
private DeckSection(int commonSize) {

View File

@@ -211,8 +211,6 @@ public class Match {
final Player player = players.get(i);
final RegisteredPlayer psc = playersConditions.get(i);
player.initVariantsZones(psc);
if (canSideBoard) {
Deck toChange = psc.getDeck();
List<PaperCard> newMain = player.getController().sideboard(toChange, rules.getGameType());
@@ -230,6 +228,8 @@ public class Match {
}
}
player.initVariantsZones(psc);
Deck myDeck = psc.getDeck();
Set<PaperCard> myRemovedAnteCards = null;

View File

@@ -18,6 +18,7 @@
package forge.game.card;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -56,6 +57,8 @@ import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.item.IPaperCard;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.Lang;
@@ -159,6 +162,50 @@ public class CardFactoryUtil {
return morphUp;
}
public static boolean handleHiddenAgenda(Player player, Card card) {
SpellAbility sa = new SpellAbility.EmptySa(card);
sa.getMapParams().put("AILogic", card.getSVar("AgendaLogic"));
Predicate<PaperCard> cpp = Predicates.alwaysTrue();
//Predicate<Card> pc = Predicates.in(player.getAllCards());
// TODO This would be better to send in the player's deck, not all cards
String name = player.getController().chooseCardName(sa, cpp, "Card", "Name a card for " + card.getName());
if (name == null || name.isEmpty()) {
return false;
}
card.setNamedCard(name);
card.turnFaceDown();
// Hopefully face down also hides the named card?
card.addSpellAbility(abilityRevealHiddenAgenda(card));
return true;
}
public static AbilityStatic abilityRevealHiddenAgenda(final Card sourceCard) {
final AbilityStatic revealAgenda = new AbilityStatic(sourceCard, Cost.Zero, null) {
@Override
public void resolve() {
if (sourceCard.turnFaceUp()) {
String sb = this.getActivatingPlayer() + " has revealed " + sourceCard.getName() + " with the chosen name " + sourceCard.getNamedCard();
sourceCard.getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
sourceCard.getGame().fireEvent(new GameEventCardStatsChanged(sourceCard));
}
}
@Override
public boolean canPlay() {
return sourceCard.getController().equals(this.getActivatingPlayer()) && sourceCard.isFaceDown()
&& sourceCard.isInZone(ZoneType.Command);
}
// TODO When should the AI activate this?
}; // reveal hidden agenda
revealAgenda.setDescription("Reveal this Hidden Agenda at any time. ");
return revealAgenda;
}
/**
* <p>
* abilityCycle.

View File

@@ -30,6 +30,7 @@ import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardPredicates.Presets;
@@ -3321,6 +3322,16 @@ public class Player extends GameEntity implements Comparable<Player> {
getZone(ZoneType.Command).add(eff);
}
for (IPaperCard cp : registeredPlayer.getConspiracies()) {
Card conspire = Card.fromPaperCard(cp, this);
if (conspire.hasKeyword("Hidden agenda")) {
if (!CardFactoryUtil.handleHiddenAgenda(this, conspire)) {
continue;
}
}
com.add(conspire);
}
}
public void changeOwnership(Card card) {

View File

@@ -27,6 +27,7 @@ public class RegisteredPlayer {
private final List<IPaperCard> cardsInCommand = new ArrayList<IPaperCard>();
private Iterable<? extends IPaperCard> schemes = null;
private Iterable<PaperCard> planes = null;
private Iterable<PaperCard> conspiracies = null;
private PaperCard commander = null;
private int teamNumber = -1; // members of teams with negative id will play FFA.
@@ -101,6 +102,15 @@ public class RegisteredPlayer {
return planes == null ? EmptyList : planes;
}
public Iterable<PaperCard> getConspiracies() {
return conspiracies == null ? EmptyList : conspiracies;
}
public void assignConspiracies() {
if (currentDeck.has(DeckSection.Conspiracy))
conspiracies = currentDeck.get(DeckSection.Conspiracy).toFlatList();
}
public int getTeamNumber() {
return teamNumber;
}

View File

@@ -139,6 +139,9 @@ public enum CSubmenuDraft implements ICDoc {
List<RegisteredPlayer> starter = new ArrayList<RegisteredPlayer>();
starter.add(new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GuiBase.getInterface().getGuiPlayer()));
starter.add(new RegisteredPlayer(aiDeck).setPlayer(GuiBase.getInterface().createAiPlayer()));
for(RegisteredPlayer pl : starter) {
pl.assignConspiracies();
}
GuiBase.getInterface().startMatch(GameType.Draft, starter);
}

View File

@@ -51,4 +51,5 @@ Dragon's Maze Race, -/5/RTR, DGM DGM DGM Meta-Choose(All(S(RTR Azorius Guild);Ra
Modern Masters, 3/6/M13, MMA
Magic 2014, 3/6/M14, M14
Theros, 3/6/THS, THS BNG JOU
#Conspiracy, 3/6/M14, CNS
Magic 2015, 3/6/M15, M15

View File

@@ -657,3 +657,47 @@
1 Vitu-Ghazi Guildmage|RTR
1 Wayfaring Temple|RTR
1 Wild Beastmaster|RTR
[CNS Draft Matters]
#1 Advantageous Proclamation|CNS
#1 AEther Searcher|CNS
#1 Agent of Acquisitions|CNS
#1 Backup Plan|CNS
1 Brago's Favor|CNS
#1 Canal Dredger|CNS
#1 Cogwork Grinder|CNS
#1 Cogwork Librarian|CNS
#1 Cogwork Spy|CNS
#1 Cogwork Tracker|CNS
#1 Deal Broker|CNS
#1 Double Stroke|CNS
1 Immediate Action|CNS
#1 Iterative Analysis|CNS
#1 Lore Seeker|CNS
#1 Lurking Automaton|CNS
1 Muzzio's Preparations|CNS
#1 Paliano, the High City|CNS
#1 Power Play|CNS
1 Secret Summoning|CNS
1 Secrets of Paradise|CNS
#1 Sentinel Dispatch|CNS
#1 Unexpected Potential|CNS
#1 Whispergear Sneak|CNS
#1 Worldknit|CNS
[M15 Sample Cards]
1 Aegis Angel|M15
1 Cancel|M15
1 Centaur Courser|M15
1 Divine Verdict|M15
1 Furnace Whelp|M15
1 Garruk's Packleader|M15
1 Inspired Charge|M15
1 Mahamoti Djinn|M15
1 Nightmare|M15
1 Seismic Strike|M15
1 Sengir Vampire|M15
1 Serra Angel|M15
1 Shivan Dragon|M15
1 Terra Stomper|M15
1 Walking Corpse|M15

View File

@@ -0,0 +1,7 @@
Name:Brago's Favor
ManaCost:no cost
Types:Conspiracy
K:Hidden agenda
S:Mode$ ReduceCost | ValidCard$ Card.NamedCard | EffectZone$ Command | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Spells of the named card cost 1 less.
SVar:AgendaLogic:BestCreatureInComputerDeck
Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nSpells with the chosen name you cast cost {1} less to cast.

View File

@@ -0,0 +1,7 @@
Name:Immediate Action
ManaCost:no cost
Types:Conspiracy
K:Hidden agenda
S:Mode$ Continuous | Affected$ Creature.YouCtrl+NamedCard | EffectZone$ Command | AddKeyword$ Haste | Description$ Creatures you control of the named card has haste.
SVar:AgendaLogic:BestCreatureInComputerDeck
Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nCreatures you control with the chosen name have haste.

View File

@@ -0,0 +1,9 @@
Name:Muzzio's Preparations
ManaCost:no cost
Types:Conspiracy
K:Hidden agenda
R:Event$ Moved | ActiveZones$ Command | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+NamedCard | ReplaceWith$ AddExtraCounter | Description$ Each creature with the named card you control enters the battlefield with an additional +1/+1 counter on it.
SVar:AddExtraCounter:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ MoveToBattlefield
SVar:MoveToBattlefield:DB$ ChangeZone | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard
SVar:AgendaLogic:MostProminentCreatureInComputerDeck
Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nEach creature you control with the chosen name enters the battlefield with an additional +1/+1 counter on it.

View File

@@ -0,0 +1,9 @@
Name:Secret Summoning
ManaCost:no cost
Types:Conspiracy
K:Hidden agenda
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.NamedCard+YouCtrl | Execute$ TrigChange | OptionalDecider$ You | TriggerDescription$ Whenever a creature with the chosen name enters the battlefield under your control, you may search your library for any number of cards with that name, reveal them, put them into your hand, then shuffle your library.
SVar:TrigChange:DB$ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Card.NamedCard | ChangeNum$ X | References$ X
SVar:X:Count$InYourLibrary
SVar:AgendaLogic:MostProminentCreatureInComputerDeck
Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nWhenever a creature with the chosen name enters the battlefield under your control, you may search your library for any number of cards with that name, reveal them, put them into your hand, then shuffle your library.

View File

@@ -0,0 +1,8 @@
Name:Secrets of Paradise
ManaCost:no cost
Types:Conspiracy
K:Hidden agenda
S:Mode$ Continuous | Affected$ Creature.YouCtrl+NamedCard | EffectZone$ Command | AddAbility$ AnyMana | Description$ Creatures of the named card you control have "{T}: Add one mana of any color to your mana pool."
SVar:AnyMana:AB$Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color to your mana pool.
SVar:AgendaLogic:MostProminentCreatureInComputerDeck
Oracle:Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.)\nCreatures you control with the chosen name have "{T}: Add one mana of any color to your mana pool."

View File

@@ -4,6 +4,8 @@ Date=2014-06-06
Name=Conspiracy
Code2=CNS
Type=Other
BoosterCovers=3
Booster=10 Common:!fromSheet("CNS Draft Matters"), 3 Uncommon:!fromSheet("CNS Draft Matters"), 1 RareMythic:!fromSheet("CNS Draft Matters"), 1 fromSheet("CNS Draft Matters")
[cards]
U Advantageous Proclamation

View File

@@ -5,7 +5,7 @@ Name=Magic 2015
Code2=M15
Type=Core
BoosterCovers=5
Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand
Booster=10 Common:!fromSheet("M15 Sample Cards"), 3 Uncommon:!fromSheet("M15 Sample Cards"), 1 RareMythic:!fromSheet("M15 Sample Cards"), 1 BasicLand
[cards]
M Ajani Steadfast