Merge remote-tracking branch 'upstream/master' into collector-number-in-card-list-and-card-db-refactoring

This commit is contained in:
leriomaggio
2021-05-26 07:58:08 +01:00
37 changed files with 2085 additions and 1845 deletions

View File

@@ -111,8 +111,7 @@ public abstract class DamageAiBase extends SpellAbilityAi {
final CardCollectionView hand = comp.getCardsIn(ZoneType.Hand);
if ((enemy.getLife() - restDamage) < 5) {
// drop the human to less than 5
// life
// drop the human to less than 5 life
return true;
}
@@ -147,12 +146,12 @@ public abstract class DamageAiBase extends SpellAbilityAi {
}
}
}
if (value > 0) { //more likely to burn with larger hand
if (value > 0) { //more likely to burn with larger hand
for (int i = 3; i < hand.size(); i++) {
value *= 1.1f;
}
}
if (value < 0.2f) { //hard floor to reduce ridiculous odds for instants over time
if (value < 0.2f) { //hard floor to reduce ridiculous odds for instants over time
return false;
} else {
final float chance = MyRandom.getRandom().nextFloat();

View File

@@ -732,12 +732,10 @@ public class DamageDealAi extends DamageAiBase {
}
// When giving priority to targeting Creatures for mandatory
// triggers
// feel free to add the Human after we run out of good targets
// triggers feel free to add the Human after we run out of good targets
// TODO: add check here if card is about to die from something
// on the stack
// or from taking combat damage
// on the stack or from taking combat damage
final Cost abCost = sa.getPayCosts();
boolean freePing = immediately || abCost == null
@@ -982,7 +980,6 @@ public class DamageDealAi extends DamageAiBase {
@Override
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
final Card source = sa.getHostCard();
final String damage = sa.getParam("NumDmg");
int dmg = AbilityUtils.calculateAmount(source, damage, sa);

View File

@@ -348,7 +348,6 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
}
list = CardLists.getValidCards(list, sIsPresent.split(","), this.getHostCard().getController(), this.getHostCard(), this);
final String rightString = presentCompare.substring(2);
int right = AbilityUtils.calculateAmount(getHostCard(), rightString, this);
final int left = list.size();

View File

@@ -62,8 +62,12 @@ public class FlipCoinEffect extends SpellAbilityEffect {
final boolean noCall = sa.hasParam("NoCall");
String varName = sa.hasParam("SaveNumFlipsToSVar") ? sa.getParam("SaveNumFlipsToSVar") : "X";
boolean victory = false;
int amount = 1;
if (sa.hasParam("Amount")) {
amount = AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa);
}
if (!noCall) {
if ((!noCall) && (amount == 1)) {
flipMultiplier = getFilpMultiplier(caller.get(0));
victory = flipCoinCall(caller.get(0), sa, flipMultiplier, varName);
}
@@ -77,11 +81,6 @@ public class FlipCoinEffect extends SpellAbilityEffect {
int countHeads = 0;
int countTails = 0;
int amount = 1;
if (sa.hasParam("Amount")) {
amount = AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa);
}
for(int i = 0; i < amount; ++i) {
final boolean resultIsHeads = flipCoinNoCall(sa, flipper, flipMultiplier, varName);
@@ -113,6 +112,43 @@ public class FlipCoinEffect extends SpellAbilityEffect {
AbilityUtils.resolve(sub);
}
}
} else if (amount > 1){
flipMultiplier = getFilpMultiplier(flipper);
int countWins = 0;
int countLosses = 0;
for(int i = 0; i < amount; ++i) {
final boolean win = flipCoinCall(caller.get(0), sa, flipMultiplier, varName);
if (win) {
countWins++;
} else {
countLosses++;
}
}
if (countWins > 0) {
SpellAbility sub = sa.getAdditionalAbility("WinSubAbility");
if (sub != null) {
sub.setSVar("Wins", "Number$" + countWins);
AbilityUtils.resolve(sub);
}
}
if (countLosses > 0) {
SpellAbility sub = sa.getAdditionalAbility("LoseSubAbility");
if (sub != null) {
sub.setSVar("Losses", "Number$" + countLosses);
AbilityUtils.resolve(sub);
}
}
if (sa.hasParam("RememberNumber")) {
String toRemember = sa.getParam("RememberNumber");
if (toRemember.startsWith("Win")) {
host.addRemembered(countWins);
} else if (toRemember.startsWith("Loss")) {
host.addRemembered(countLosses);
}
}
} else {
if (victory) {
if (sa.getParam("RememberWinner") != null) {

View File

@@ -5487,7 +5487,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public final void setRandomFoil() {
setFoil(CardEdition.getRandomFoil(getSetCode()));
}
public final void setFoil(final int f) {
currentState.setSVar("Foil", Integer.toString(f));
}
@@ -5531,9 +5530,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return pairedWith != null;
}
public Card getMeldedWith() { return meldedWith; }
public void setMeldedWith(Card meldedWith) { this.meldedWith = meldedWith; }
public Card getMeldedWith() { return meldedWith; }
public void setMeldedWith(Card meldedWith) { this.meldedWith = meldedWith; }
public boolean hasProtectionFrom(final Card source) {
return hasProtectionFrom(source, false, false);

View File

@@ -51,12 +51,10 @@ import forge.util.collect.FCollection;
* @version $Id$
*/
public class SpellAbilityRestriction extends SpellAbilityVariables {
// A class for handling SpellAbility Restrictions. These restrictions
// include:
// A class for handling SpellAbility Restrictions. These restrictions include:
// Zone, Phase, OwnTurn, Speed (instant/sorcery), Amount per Turn, Player,
// Threshold, Metalcraft, LevelRange, etc
// Each value will have a default, that can be overridden (mostly by
// AbilityFactory)
// Each value will have a default, that can be overridden (mostly by AbilityFactory)
// The canPlay function will use these values to determine if the current
// game state is ok with these restrictions
@@ -246,7 +244,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
// NOTE: this assumes that it's always possible to cast cards from hand and you don't
// need special permissions for that. If WotC ever prints a card that forbids casting
// cards from hand, this may become relevant.
if (!o.grantsZonePermissions() && cardZone != null && !cardZone.is(ZoneType.Hand)) {
if (!o.grantsZonePermissions() && cardZone != null && (!cardZone.is(ZoneType.Hand) || activator != c.getOwner())) {
final List<CardPlayOption> opts = c.mayPlay(activator);
boolean hasOtherGrantor = false;
for (CardPlayOption opt : opts) {
@@ -265,13 +263,13 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
}
if (params.containsKey("Affected")) {
if (!cp.isValid(params.get("Affected").split(","), activator, o.getHost(), null)) {
if (!cp.isValid(params.get("Affected").split(","), activator, o.getHost(), o.getAbility())) {
return false;
}
}
if (params.containsKey("ValidSA")) {
if (!sa.isValid(params.get("ValidSA").split(","), activator, o.getHost(), null)) {
if (!sa.isValid(params.get("ValidSA").split(","), activator, o.getHost(), o.getAbility())) {
return false;
}
}

View File

@@ -732,7 +732,6 @@ public final class StaticAbilityContinuous {
}
if (layer == StaticAbilityLayer.ABILITIES) {
List<SpellAbility> addedAbilities = Lists.newArrayList();
List<ReplacementEffect> addedReplacementEffects = Lists.newArrayList();
List<Trigger> addedTrigger = Lists.newArrayList();

View File

@@ -340,7 +340,7 @@ public abstract class Trigger extends TriggerReplacementBase {
}
}
if ( !meetsCommonRequirements(this.mapParams))
if (!meetsCommonRequirements(this.mapParams))
return false;
return true;

View File

@@ -254,6 +254,14 @@ public class TriggerSpellAbilityCastOrCopy extends Trigger {
}
}
if (hasParam("NoColoredMana")) {
for (Mana m : spellAbility.getPayingMana()) {
if (!m.isColorless()) {
return false;
}
}
}
if (hasParam("SnowSpentForCardsColor")) {
boolean found = false;
for (Mana m : spellAbility.getPayingMana()) {

View File

@@ -3,7 +3,7 @@ ManaCost:2 U
Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ At the beginning of your upkeep, put a time counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ TIME | CounterNum$ 1
S:Mode$ Continuous | MayPlay$ True | MayPlayAltManaCost$ 0 | MayPlayLimit$ 1 | MayPlayDontGrantZonePermissions$ True | Affected$ Card.YouCtrl+nonLand+cmcLEX | AffectedZone$ Hand,Graveyard,Library,Exile,Command | Description$ Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with mana value X or less, where X is the number of time counters on CARDNAME.
S:Mode$ Continuous | MayPlay$ True | MayPlayAltManaCost$ 0 | MayPlayLimit$ 1 | MayPlayDontGrantZonePermissions$ True | Affected$ Card.nonLand+cmcLEX | AffectedZone$ Hand,Graveyard,Library,Exile,Command | Description$ Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with mana value X or less, where X is the number of time counters on CARDNAME.
SVar:X:Count$CardCounters.TIME
SVar:Picture:http://www.wizards.com/global/images/magic/general/as_foretold.jpg
Oracle:At the beginning of your upkeep, put a time counter on As Foretold.\nOnce each turn, you may pay {0} rather than pay the mana cost for a spell you cast with mana value X or less, where X is the number of time counters on As Foretold.

View File

@@ -3,7 +3,7 @@ ManaCost:3 R
Types:Enchantment
S:Mode$ CantBeCast | NonCasterTurn$ True | Caster$ You | Description$ You can cast spells only during your turn and you can cast no more than two spells each turn.
S:Mode$ CantBeCast | NumLimitEachTurn$ 2 | Caster$ You | Secondary$ True | Description$ You can cast spells only during your turn and you can cast no more than two spells each turn.
S:Mode$ Continuous | Affected$ Card.nonLand+YouOwn+cmcLEX | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand,Graveyard,Exile,Command,Library | MayPlayDontGrantZonePermissions$ True | Description$ You may cast spells with mana value less than or equal to the number of lands you control without paying their mana costs.
S:Mode$ Continuous | Affected$ Card.nonLand+cmcLEX | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand,Graveyard,Exile,Command,Library | MayPlayDontGrantZonePermissions$ True | Description$ You may cast spells with mana value less than or equal to the number of lands you control without paying their mana costs.
SVar:X:Count$Valid Land.YouCtrl
AI:RemoveDeck:Random
SVar:NonStackingEffect:True

View File

@@ -2,8 +2,8 @@ Name:Mimic Vat
ManaCost:3
Types:Artifact
T:Mode$ ChangesZone | ValidCard$ Creature.nonToken | Origin$ Battlefield | Destination$ Graveyard | OptionalDecider$ You | Execute$ TrigReturn | TriggerZones$ Battlefield | TriggerDescription$ Imprint — Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with CARDNAME to its owner's graveyard.
SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Graveyard | Defined$ Imprinted | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True | SubAbility$ DBExile
SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Graveyard | Defined$ Imprinted | SubAbility$ DBCleanup | ConditionPresent$ Card.inRealZone Graveyard | ConditionDefined$ TriggeredNewCardLKICopy | ConditionCompare$ EQ1
SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True | SubAbility$ DBExile | ConditionPresent$ Card.inRealZone Graveyard | ConditionDefined$ TriggeredNewCardLKICopy | ConditionCompare$ EQ1
SVar:DBExile:DB$ ChangeZone | Imprint$ True | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | AILogic$ MimicVat
A:AB$ CopyPermanent | Cost$ 3 T | Defined$ Imprinted.ExiledWithSource | Choices$ Card | PumpKeywords$ Haste | AtEOT$ Exile | AILogic$ MimicVat | SpellDescription$ Create a token that's a copy of a card exiled with CARDNAME. It gains haste. Exile it at the beginning of the next end step.
T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsImprinted+ExiledWithSource | Execute$ DBForget

View File

@@ -22,7 +22,7 @@ ManaCost:3 R R
Types:Legendary Creature Efreet Shaman
PT:4/4
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | TriggerDescription$ At the beginning of your upkeep, exile the top card of each opponent's library. Until end of turn, you may cast spells from among those exiled cards, and you may spend mana as though it were mana of any color to cast those spells.
SVar:TrigExile:DB$ Dig | Defined$ Player.Opponent | DigNum$ 1 | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top card of each opponent's library. Until end of turn, you may cast nonland cards from among those exiled cards, and you may spend mana as though it were mana of any color to cast those spells.
SVar:TrigExile:DB$ Dig | Defined$ Player.Opponent | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top card of each opponent's library. Until end of turn, you may cast nonland cards from among those exiled cards, and you may spend mana as though it were mana of any color to cast those spells.
SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | Triggers$ TriggerCast | RememberObjects$ Remembered | SubAbility$ DBCleanup
SVar:STPlay:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonLand | AffectedZone$ Exile | Description$ Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast it.
SVar:TriggerCast:Mode$ SpellCast | ValidCard$ Card.IsRemembered | TriggerZones$ Command | Execute$ TrigRemoveSelf | Static$ True

View File

@@ -0,0 +1,10 @@
Name:Break Ties
ManaCost:2 W
Types:Instant
K:Reinforce:1:W
A:SP$ Charm | Choices$ DBDestroyArtifact,DBDestroyEnchantment,DBExile
SVar:DBDestroyArtifact:DB$ Destroy | ValidTgts$ Artifact | TgtPrompt$ Select target artifact | SpellDescription$ Destroy target artifact.
SVar:DBDestroyEnchantment:DB$ Destroy | ValidTgts$ Enchantment | TgtPrompt$ Select target enchantment | SpellDescription$ Destroy target enchantment.
SVar:DBExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Card | TgtPrompt$ Select target card from a graveyard. | SpellDescription$ Exile target card from a graveyard.
DeckHas:Ability$Counters
Oracle:Choose one —\n• Destroy target artifact.\n• Destroy target enchantment.\n• Exile target card from a graveyard.\nReinforce 1—{W} ({W}, Discard this card: Put a +1/+1 counter on target creature.)

View File

@@ -0,0 +1,14 @@
Name:Chatterfang, Squirrel General
ManaCost:2 G
Types:Legendary Creature Squirrel Warrior
PT:3/3
K:Forestwalk
R:Event$ CreateToken | ActiveZones$ Battlefield | ValidPlayer$ You | ReplaceWith$ DBReplace | Description$ If one or more tokens would be created under your control, those tokens plus that many 1/1 green Squirrel creature tokens are created instead.
SVar:DBReplace:DB$ ReplaceEffect | VarName$ TokenNum | VarValue$ Y | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenAmount$ Y | TokenScript$ g_1_1_squirrel
A:AB$ Pump | Cost$ B Sac<X/Squirrel> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | NumDef$ -X | SpellDescription$ Target creature gets +X/-X until end of turn.
SVar:X:Count$xPaid
SVar:Y:ReplaceCount$TokenNum
DeckHas:Ability$Token
DeckHints:Type$Squirrel
Oracle:Forestwalk (This creature can't be blocked as long as defending player controls a Forest.)\nIf one or more tokens would be created under your control, those tokens plus that many 1/1 green Squirrel creature tokens are created instead.\n{B}, Sacrifice X Squirrels: Target creature gets +X/-X until end of turn.

View File

@@ -0,0 +1,11 @@
Name:Dakkon, Shadow Slayer
ManaCost:W U B
Types:Legendary Planeswalker Dakkon
Loyalty:0
K:etbCounter:LOYALTY:X:no Condition:CARDNAME enters the battlefield with a number of loyalty counters on him equal to the number of lands you control.
SVar:X:Count$Valid Land.YouCtrl
A:AB$ Surveil | Cost$ AddCounter<1/LOYALTY> | Amount$ 2 | Planeswalker$ True | SpellDescription$ Surveil 2. (Look at the top two cards of your library, then put any number of them into your graveyard and the rest on top of your library in any order.)
A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile target creature.
A:AB$ ChangeZone | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ChangeType$ Artifact.YouOwn | ChangeNum$ 1 | Origin$ Hand,Graveyard | Destination$ Battlefield | StackDescription$ SpellDescription | SpellDescription$ You may put an artifact card from your hand or graveyard onto the battlefield.
DeckHints:Type$Artifact
Oracle:Dakkon, Shadow Slayer enters the battlefield with a number of loyalty counters on him equal to the number of lands you control.\n[+1]: Surveil 2.\n[3]: Exile target creature.\n[-6]: You may put an artifact card from your hand or graveyard onto the battlefield.

View File

@@ -0,0 +1,13 @@
Name:Flametongue Yearling
ManaCost:R R
Types:Creature Kavu
PT:2/1
K:Multikicker:2
K:etbCounter:P1P1:XKicked:no condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each time it was kicked.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDealDamage | TriggerDescription$ When CARDNAME enters the battlefield, it deals damage equal to its power to target creature.
SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ Y
SVar:X:Count$CardCounters.P1P1
SVar:XKicked:Count$TimesKicked
SVar:Y:Count$CardPower
DeckHas:Ability$Counters
Oracle:Multikicker {2} (You may pay an additional {2} any number of times as you cast this spell.)\nFlametongue Yearling enters the battlefield with a +1/+1 counter on it for each time it was kicked.\nWhen Flametongue Yearling enters the battlefield, it deals damage equal to its power to target creature.

View File

@@ -0,0 +1,9 @@
Name:Fractured Sanity
ManaCost:U U U
Types:Sorcery
K:Cycling:1 U
A:SP$ Mill | Defined$ Opponent | NumCards$ 14 | SpellDescription$ Each opponent mills fourteen cards.
T:Mode$ Cycled | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ When you cycle CARDNAME, each opponent mills four cards.
SVar:TrigMill:DB$ Mill | Defined$ Opponent | NumCards$ 4
DeckHas:Ability$Mill
Oracle:Each opponent mills fourteen cards.\nCycling {1}{U}\nWhen you cycle Fractured Sanity, each opponent mills four cards.

View File

@@ -0,0 +1,9 @@
Name:Grief
ManaCost:2 B B
Types:Creature Elemental Incarnation
PT:3/2
K:Menace
K:Evoke:ExileFromHand<1/Card.Black+Other>
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRemove | TriggerDescription$ When CARDNAME enters the battlefield, target opponent reveals their hand. You choose a nonland card from it. That player discards that card.
SVar:TrigRemove:DB$ Discard | ValidTgts$ Opponent | NumCards$ 1 | Mode$ RevealYouChoose | DiscardValid$ Card.nonLand | SpellDescription$ Target opponent reveals their hand. You choose a nonland card from it. That player discards that card.
Oracle:Menace\nWhen Grief enters the battlefield, target opponent reveals their hand. You choose a nonland card from it. That player discards that card.\nEvoke — Exile a black card from your hand.

View File

@@ -0,0 +1,7 @@
Name:Late to Dinner
ManaCost:3 W
Types:Sorcery
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Choose target creature card in your graveyard | SubAbility$ DBToken | SpellDescription$ Return target creature card from your graveyard to the battlefield. Create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
SVar:DBToken:DB$ Token | TokenScript$ c_a_food_sac
DeckHas:Ability$Graveyard & Ability$Token & Ability$Sacrifice & Ability$LifeGain
Oracle:Return target creature card from your graveyard to the battlefield. Create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")

View File

@@ -0,0 +1,16 @@
Name:Lolth, Spider Queen
ManaCost:3 B B
Types:Legendary Planeswalker Lolth
Loyalty:4
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a creature you control dies, put a loyalty counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ LOYALTY | CounterNum$ 1
A:AB$ Draw | Cost$ AddCounter<0/LOYALTY> | NumCards$ 1 | SubAbility$ DBLoseLife1 | Planeswalker$ True | SpellDescription$ You draw a card and you lose 1 life.
SVar:DBLoseLife1:DB$ LoseLife | LifeAmount$ 1
A:AB$ Token | Cost$ SubCounter<3/LOYALTY> | TokenAmount$ 2 | TokenScript$ b_2_1_spider_menace_reach | TokenOwner$ You | Planeswalker$ True | SpellDescription$ Create two 2/1 black Spider creature tokens with menace and reach.
A:AB$ Effect | Cost$ SubCounter<8/LOYALTY> | Name$ Emblem - Lolth, Spider Queen | Triggers$ TrigLoseLife | Planeswalker$ True | Ultimate$ True | Duration$ Permanent | AILogic$ Main1 | SpellDescription$ You get an emblem with "Whenever an opponent is dealt combat damage by one or more creatures you control, if that player lost less than 8 life this turn, they lose life equal to the difference."
SVar:TrigLoseLife:Mode$ DamageDoneOnce | ValidSource$ Creature.YouCtrl | ValidTarget$ Player | CombatDamage$ True | CheckSVar$ X | SVarCompare$ LT8 | Execute$ LoseLife | TriggerZones$ Command | TriggerDescription$ Whenever an opponent is dealt combat damage by one or more creatures you control, if that player lost less than 8 life this turn, they lose life equal to the difference.
SVar:LoseLife:DB$ LoseLife | Defined$ TriggeredTarget | LifeAmount$ Y | SubAbility$ Cleanup
SVar:Cleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:TriggeredTarget$LifeLostThisTurn
SVar:Y:SVar$X/NMinus.8
Oracle:Whenever a creature you control dies, put a loyalty counter on Lolth, Spider Queen.\n[0]: You draw a card and you lose 1 life.\n[3]: Create two 2/1 black Spider creature tokens with menace and reach.\n[8]: You get an emblem with "Whenever an opponent is dealt combat damage by one or more creatures you control, if that player lost less than 8 life this turn, they lose life equal to the difference."

View File

@@ -0,0 +1,7 @@
Name:Lucid Dreams
ManaCost:3 U U
Types:Sorcery
A:SP$ Draw | NumCards$ X | SpellDescription$ Draw X cards, where X is the number of card types among cards in your graveyard.
SVar:X:Count$CardControllerTypes.Graveyard
DeckHints:Ability$Discard & Ability$Graveyard
Oracle:Draw X cards, where X is the number of card types among cards in your graveyard.

View File

@@ -0,0 +1,8 @@
Name:Prismatic Ending
ManaCost:X W
Types:Sorcery
A:SP$ ChangeZone | Cost$ X W | ValidTgts$ Permanent.nonLand | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select target nonland permanent | ConditionDefined$ Targeted | ConditionPresent$ Permanent.nonLand+cmcLEY | ConditionCompare$ EQ1 | SpellDescription$ Exile target nonland permanent if its mana value is less than or equal to the number of colors of mana spent to cast this spell.
SVar:X:Count$xPaid
SVar:Y:Count$Converge
AI:RemoveDeck:All
Oracle:Converge — Exile target nonland permanent if its mana value is less than or equal to the number of colors of mana spent to cast this spell.

View File

@@ -0,0 +1,7 @@
Name:Profane Tutor
ManaCost:no cost
Types:Sorcery
Colors:black
K:Suspend:2:1 B
A:SP$ ChangeZone | Cost$ 0 | Origin$ Library | Destination$ Hand | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True | SpellDescription$ Search your library for a card, put that card into your hand, then shuffle.
Oracle:Suspend 2—{1}{B} (Rather than cast this card from your hand, pay {1}{B} and exile it with two time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost.)\nSearch your library for a card, put that card into your hand, then shuffle.

View File

@@ -0,0 +1,10 @@
Name:Ravenous Squirrel
ManaCost:BG
Types:Creature Squirrel
PT:1/1
T:Mode$ Sacrificed | ValidCard$ Artifact.YouCtrl,Creature.YouCtrl | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever you sacrifice an artifact or creature, put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
A:AB$ GainLife | Cost$ 1 B G Sac<1/Artifact;Creature/artifact or creature> | Defined$ You | LifeAmount$ 1 | SubAbility$ DBDraw | SpellDescription$ You gain 1 life and draw a card.
SVar:DBDraw:DB$ Draw | NumCards$ 1
DeckHas:Ability$Sacrifice & Ability$Counters & Ability$LifeGain
Oracle:Whenever you sacrifice an artifact or creature, put a +1/+1 counter on Ravenous Squirrel.\n{1}{B}{G}, Sacrifice an artifact or creature: You gain 1 life and draw a card.

View File

@@ -0,0 +1,7 @@
Name:Rishadan Dockhand
ManaCost:U
Types:Creature Merfolk
PT:1/2
K:Islandwalk
A:AB$ Tap | Cost$ 1 T | ValidTgts$ Land | TgtPrompt$ Select target land | SpellDescription$ Tap target land.
Oracle:Islandwalk\n{1}, {T}: Tap target land.

View File

@@ -0,0 +1,6 @@
Name:Spreading Insurrection
ManaCost:4 R
Types:Sorcery
K:Storm
A:SP$ GainControl | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SpellDescription$ Gain control of target creature you don't control until end of turn. Untap that creature. It gains haste until end of turn.
Oracle:Gain control of target creature you don't control until end of turn. Untap that creature. It gains haste until end of turn.\nStorm (When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.)

View File

@@ -0,0 +1,9 @@
Name:Squirrel Sanctuary
ManaCost:G
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 1/1 green Squirrel creature token.
SVar:TrigToken:DB$ Token | TokenScript$ g_1_1_squirrel
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouCtrl+nonToken | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ Whenever a nontoken creature you control dies, you may pay {1}. If you do, return CARDNAME to its owner's hand.
SVar:TrigReturn:AB$ ChangeZone | Cost$ 1 | Origin$ Battlefield | Destination$ Hand | Defined$ Self
DeckHas:Ability$Token
Oracle:When Squirrel Sanctuary enters the battlefield, create a 1/1 green Squirrel creature token.\nWhenever a nontoken creature you control dies, you may pay {1}. If you do, return Squirrel Sanctuary to its owner's hand.

View File

@@ -0,0 +1,8 @@
Name:Squirrel Sovereign
ManaCost:1 G
Types:Creature Squirrel Noble
PT:2/2
S:Mode$ Continuous | Affected$ Creature.Squirrel+Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Other Squirrels you control get +1/+1.
SVar:PlayMain1:TRUE
DeckNeeds:Type$Squirrel
Oracle:Other Squirrels you control get +1/+1.

View File

@@ -0,0 +1,9 @@
Name:Timeless Dragon
ManaCost:3 W W
Types:Creature Dragon
PT:5/5
K:Flying
K:TypeCycling:Plains:2
K:Eternalize:2 W W
DeckHas:Ability$Token
Oracle:Flying\nPlainscycling {2} ({2}, Discard this card: Search your library for a Plains card, reveal it, put it into your hand, then shuffle.)\nEternalize {2}{W}{W} ({2}{W}{W}, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Dragon with no mana cost. Eternalize only as a sorcery.)

View File

@@ -0,0 +1,6 @@
Name:Tourach's Canticle
ManaCost:3 B
Types:Sorcery
A:SP$ Discard | ValidTgts$ Opponent | Mode$ RevealYouChoose | NumCards$ 1 | SubAbility$ DiscardRandom | SpellDescription$ Target opponent reveals their hand. You choose a card from it. That player discards that card, then discards a card at random.
SVar:DiscardRandom:DB$ Discard | Defined$ Targeted | NumCards$ 1 | Mode$ Random
Oracle:Target opponent reveals their hand. You choose a card from it. That player discards that card, then discards a card at random.

View File

@@ -0,0 +1,7 @@
Name:Unmarked Grave
ManaCost:1 B
Types:Sorcery
A:SP$ ChangeZone | Cost$ 1 B | Origin$ Library | Destination$ Graveyard | ChangeType$ Card.nonLegendary | ChangeNum$ 1 | SpellDescription$ Search your library for a nonlegendary card, put that card into your graveyard, then shuffle.
DeckHas:Ability$Graveyard
AI:RemoveDeck:Random
Oracle:Search your library for a nonlegendary card, put that card into your graveyard, then shuffle.

View File

@@ -0,0 +1,6 @@
Name:Void Mirror
ManaCost:2
Types:Artifact
T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | Execute$ TrigCounter | NoColoredMana$ True | TriggerDescription$ Whenever a player casts a spell, if no colored mana was spent to cast it, counter that spell.
SVar:TrigCounter:DB$ Counter | Defined$ TriggeredSpellAbility
Oracle:Whenever a player casts a spell, if no colored mana was spent to cast it, counter that spell.

View File

@@ -0,0 +1,17 @@
Name:Yusri, Fortune's Flame
ManaCost:1 U R
Types:Legendary Creature Efreet
PT:2/3
K:Flying
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChooseNumber | TriggerDescription$ Whenever CARDNAME attacks, choose a number between 1 and 5. Flip that many coins. For each flip you win, draw a card. For each flip you lose, NICKNAME deals 2 damage to you. If you won five flips this way, you may cast spells from your hand this turn without paying their mana costs.
SVar:TrigChooseNumber:DB$ ChooseNumber | Defined$ You | Min$ 1 | Max$ 5 | AILogic$ Max | SubAbility$ FlipCoin
SVar:FlipCoin:DB$ FlipACoin | Amount$ X | WinSubAbility$ DBDraw | LoseSubAbility$ DBDamage | RememberNumber$ Wins | SubAbility$ DBEffect
SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ Wins
SVar:DBDamage:DB$ DealDamage | NumDmg$ Damage | Defined$ You
SVar:DBEffect:DB$ Effect | StaticAbilities$ MayPlay | Stackable$ False | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ5 | SubAbility$ DBCleanup
SVar:MayPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.nonLand+YouOwn | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand | Description$ You may cast spells from your hand this turn without paying their mana costs.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Number$ChosenNumber
SVar:Y:Count$RememberedNumber
SVar:Damage:SVar$Losses/Times.2
Oracle:Flying\nWhenever Yusri, Fortune's Flame attacks, choose a number between 1 and 5. Flip that many coins. For each flip you win, draw a card. For each flip you lose, Yusri deals 2 damage to you. If you won five flips this way, you may cast spells from your hand this turn without paying their mana costs.

File diff suppressed because it is too large Load Diff

View File

@@ -317,6 +317,7 @@ Bolas
Calix
Chandra
Dack
Dakkon
Daretti
Davriel
Domri

View File

@@ -62,6 +62,7 @@ import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardFaceView;
import forge.game.card.CardLists;
import forge.game.card.CardPlayOption;
import forge.game.card.CardPredicates;
import forge.game.card.CardUtil;
import forge.game.card.CardView;
@@ -266,10 +267,19 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
final ITriggerEvent triggerEvent) {
// make sure another human player can't choose opponents cards just because he might see them
if (triggerEvent != null && !hostCard.isInZone(ZoneType.Battlefield) && !hostCard.getOwner().equals(player) &&
!hostCard.getController().equals(player) && hostCard.mayPlay(player).size() == 0 &&
!hostCard.getController().equals(player) &&
// If player cast Shaman's Trance, they can play spells from any Graveyard (if other effects allow it to be cast)
(!player.hasKeyword("Shaman's Trance") || !hostCard.isInZone(ZoneType.Graveyard))) {
return null;
boolean noPermission = true;
for (CardPlayOption o : hostCard.mayPlay(player)) {
if (o.grantsZonePermissions()) {
noPermission = false;
break;
}
}
if (noPermission) {
return null;
}
}
spellViewCache = SpellAbilityView.getMap(abilities);
final SpellAbilityView resultView = getGui().getAbilityToPlay(CardView.get(hostCard),