Merge remote-tracking branch 'origin/master'

This commit is contained in:
George
2023-01-06 11:37:22 +02:00
31 changed files with 505 additions and 74 deletions

View File

@@ -1063,6 +1063,10 @@ public class ComputerUtil {
return true;
}
if (cardState.hasKeyword(Keyword.EXALTED) || cardState.hasKeyword(Keyword.EXTORT)) {
return true;
}
if (cardState.hasKeyword(Keyword.RIOT) && ChooseGenericEffectAi.preferHasteForRiot(sa, ai)) {
// Planning to choose Haste for Riot, so do this in Main 1
return true;
@@ -1070,6 +1074,7 @@ public class ComputerUtil {
// if we have non-persistent mana in our pool, would be good to try to use it and not waste it
if (ai.getManaPool().willManaBeLostAtEndOfPhase()) {
// TODO should check if some will be kept and skip those
boolean canUseToPayCost = false;
for (byte color : ManaAtom.MANATYPES) {
// tries to reuse any amount of colorless if cost only has generic
@@ -1089,10 +1094,6 @@ public class ComputerUtil {
return true;
}
if (cardState.hasKeyword(Keyword.EXALTED) || cardState.hasKeyword(Keyword.EXTORT)) {
return true;
}
//cast equipments in Main1 when there are creatures to equip and no other unequipped equipment
if (card.isEquipment()) {
boolean playNow = false;

View File

@@ -93,6 +93,7 @@ public class ComputerUtilMana {
ability.setActivatingPlayer(card.getController(), true);
if (ability.isManaAbility()) {
score += ability.calculateScoreForManaAbility();
// TODO check TriggersWhenSpent
}
else if (!ability.isTrigger() && ability.isPossible()) {
score += 13; //add 13 for any non-mana activated abilities
@@ -393,9 +394,9 @@ public class ComputerUtilMana {
String manaProduced = toPay.isSnow() && hostCard.isSnow() ? "S" : GameActionUtil.generatedTotalMana(saPayment);
//String originalProduced = manaProduced;
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromPlayer(ai);
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(hostCard);
repParams.put(AbilityKey.Mana, manaProduced);
repParams.put(AbilityKey.Affected, hostCard);
repParams.put(AbilityKey.Activator, ai);
repParams.put(AbilityKey.AbilityMana, saPayment); // RootAbility
// TODO Damping Sphere might replace later?
@@ -1614,9 +1615,9 @@ public class ComputerUtilMana {
// setup produce mana replacement effects
String origin = mp.getOrigProduced();
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromPlayer(ai);
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(sourceCard);
repParams.put(AbilityKey.Mana, origin);
repParams.put(AbilityKey.Affected, sourceCard);
repParams.put(AbilityKey.Activator, ai);
repParams.put(AbilityKey.AbilityMana, m); // RootAbility
List<ReplacementEffect> reList = game.getReplacementHandler().getReplacementList(ReplacementType.ProduceMana, repParams, ReplacementLayer.Other);

View File

@@ -266,6 +266,7 @@ public class ManaEffectAi extends SpellAbilityAi {
ManaPool mp = ai.getManaPool();
Mana test = null;
if (mp.isEmpty()) {
// TODO use color from ability
test = new Mana((byte) ManaAtom.COLORLESS, source, null);
mp.addMana(test, false);
}

View File

@@ -101,7 +101,7 @@ public class ManifestAi extends SpellAbilityAi {
repParams.put(AbilityKey.Origin, card.getZone().getZoneType());
repParams.put(AbilityKey.Destination, ZoneType.Battlefield);
repParams.put(AbilityKey.Source, sa.getHostCard());
List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList(ReplacementType.Moved, repParams, ReplacementLayer.Other);
List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList(ReplacementType.Moved, repParams, ReplacementLayer.CantHappen);
if (!list.isEmpty()) {
return false;
}

View File

@@ -164,8 +164,8 @@ public class GameAction {
}
if (!found) {
c.clearControllers();
if (c.removeChangedState()) {
c.updateStateForView();
if (cause != null) {
unanimateOnAbortedChange(cause, c);
}
return c;
}
@@ -365,7 +365,18 @@ public class GameAction {
copied.getOwner().removeInboundToken(copied);
if (repres == ReplacementResult.Prevented) {
if (game.getStack().isResolving(c) && !zoneTo.is(ZoneType.Graveyard)) {
c.clearEtbCounters();
c.clearControllers();
if (cause != null) {
unanimateOnAbortedChange(cause, c);
if (cause.hasParam("Transformed") || cause.hasParam("FaceDown")) {
c.setBackSide(false);
c.changeToState(CardStateName.Original);
}
unattachCardLeavingBattlefield(c);
}
if (c.isInZone(ZoneType.Stack) && !zoneTo.is(ZoneType.Graveyard)) {
return moveToGraveyard(c, cause, params);
}
@@ -373,10 +384,8 @@ public class GameAction {
copied.clearDelved();
copied.clearConvoked();
copied.clearExploited();
}
// was replaced with another Zone Change
if (toBattlefield && !c.isInPlay()) {
} else if (toBattlefield && !c.isInPlay()) {
// was replaced with another Zone Change
if (c.removeChangedState()) {
c.updateStateForView();
}
@@ -2560,4 +2569,17 @@ public class GameAction {
}
return false;
}
private static void unanimateOnAbortedChange(final SpellAbility cause, final Card c) {
if (cause.hasParam("AnimateSubAbility")) {
long unanimateTimestamp = Long.valueOf(cause.getAdditionalAbility("AnimateSubAbility").getSVar("unanimateTimestamp"));
c.removeChangedCardKeywords(unanimateTimestamp, 0);
c.removeChangedCardTypes(unanimateTimestamp, 0);
c.removeChangedName(unanimateTimestamp, 0);
c.removeNewPT(unanimateTimestamp, 0);
if (c.removeChangedCardTraits(unanimateTimestamp, 0)) {
c.updateStateForView();
}
}
}
}

View File

@@ -136,10 +136,10 @@ public class AnimateAllEffect extends AnimateEffectBase {
CardCollectionView list;
if (!sa.usesTargeting() && !sa.hasParam("Defined")) {
list = game.getCardsIn(ZoneType.Battlefield);
} else {
if (sa.usesTargeting() || sa.hasParam("Defined")) {
list = getTargetPlayers(sa).getCardsIn(ZoneType.Battlefield);
} else {
list = game.getCardsIn(ZoneType.Battlefield);
}
list = CardLists.getValidCards(list, valid, sa.getActivatingPlayer(), host, sa);
@@ -155,18 +155,18 @@ public class AnimateAllEffect extends AnimateEffectBase {
game.fireEvent(new GameEventCardStatsChanged(c));
final GameCommand unanimate = new GameCommand() {
private static final long serialVersionUID = -5861759814760561373L;
@Override
public void run() {
doUnanimate(c, timestamp);
game.fireEvent(new GameEventCardStatsChanged(c));
}
};
if (!permanent) {
final GameCommand unanimate = new GameCommand() {
private static final long serialVersionUID = -5861759814760561373L;
@Override
public void run() {
doUnanimate(c, timestamp);
game.fireEvent(new GameEventCardStatsChanged(c));
}
};
addUntilCommand(sa, unanimate);
}
}

View File

@@ -94,8 +94,7 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
if (!libCards.isEmpty()) {
sa.getActivatingPlayer().getController().reveal(libCards, ZoneType.Library, libCards.get(0).getOwner());
}
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.Player, sa.getActivatingPlayer());
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(sa.getActivatingPlayer());
runParams.put(AbilityKey.Target, tgtPlayers);
game.getTriggerHandler().runTrigger(TriggerType.SearchedLibrary, runParams, false);
}
@@ -171,9 +170,11 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
// need LKI before Animate does apply
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(c));
final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility");
source.addRemembered(c);
AbilityUtils.resolve(sa.getAdditionalAbility("AnimateSubAbility"));
AbilityUtils.resolve(animate);
source.removeRemembered(c);
animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp()));
}
if (sa.hasParam("Tapped")) {
c.setTapped(true);

View File

@@ -575,6 +575,17 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
movedCard = game.getAction().moveToLibrary(gameCard, libraryPosition, sa);
} else {
if (destination.equals(ZoneType.Battlefield)) {
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield);
moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard);
if (sa.isReplacementAbility()) {
ReplacementEffect re = sa.getReplacementEffect();
moveParams.put(AbilityKey.ReplacementEffect, re);
if (ReplacementType.Moved.equals(re.getMode()) && sa.getReplacingObject(AbilityKey.CardLKI) != null) {
moveParams.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
}
}
if (sa.hasParam("Tapped") || sa.isNinjutsu()) {
gameCard.setTapped(true);
}
@@ -583,6 +594,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
if (sa.hasParam("Transformed")) {
if (gameCard.isDoubleFaced()) {
// need LKI before Animate does apply
if (!moveParams.containsKey(AbilityKey.CardLKI)) {
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(gameCard));
}
gameCard.changeCardState("Transform", null, sa);
} else {
// If it can't Transform, don't change zones.
@@ -650,26 +665,17 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
}
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield);
moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard);
if (sa.isReplacementAbility()) {
ReplacementEffect re = sa.getReplacementEffect();
moveParams.put(AbilityKey.ReplacementEffect, re);
if (ReplacementType.Moved.equals(re.getMode()) && sa.getReplacingObject(AbilityKey.CardLKI) != null) {
moveParams.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
}
}
if (sa.hasAdditionalAbility("AnimateSubAbility")) {
// need LKI before Animate does apply
if (!moveParams.containsKey(AbilityKey.CardLKI)) {
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(gameCard));
}
final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility");
hostCard.addRemembered(gameCard);
AbilityUtils.resolve(sa.getAdditionalAbility("AnimateSubAbility"));
AbilityUtils.resolve(animate);
hostCard.removeRemembered(gameCard);
animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp()));
}
// need to be facedown before it hits the battlefield in case of Replacement Effects or Trigger
@@ -776,7 +782,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
if (sa.hasParam("TrackDiscarded")) {
movedCard.setMadnessWithoutCast(true);
movedCard.setDiscarded(true);
}
}
}
@@ -1310,9 +1316,11 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
// need LKI before Animate does apply
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(c));
final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility");
source.addRemembered(c);
AbilityUtils.resolve(sa.getAdditionalAbility("AnimateSubAbility"));
AbilityUtils.resolve(animate);
source.removeRemembered(c);
animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp()));
}
if (sa.hasParam("GainControl")) {
final String g = sa.getParam("GainControl");
@@ -1331,6 +1339,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
if (sa.hasParam("Transformed")) {
if (c.isDoubleFaced()) {
// need LKI before Animate does apply
if (!moveParams.containsKey(AbilityKey.CardLKI)) {
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(c));
}
c.changeCardState("Transform", null, sa);
} else {
// If it can't Transform, don't change zones.
@@ -1390,7 +1402,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
movedCard.setTimestamp(ts);
if (sa.hasParam("AttachAfter") && movedCard.isAttachment()) {
if (sa.hasParam("AttachAfter") && movedCard.isAttachment() && movedCard.isInPlay()) {
CardCollection list = AbilityUtils.getDefinedCards(source, sa.getParam("AttachAfter"), sa);
if (list.isEmpty()) {
list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), sa.getParam("AttachAfter"), c.getController(), c, sa);

View File

@@ -417,13 +417,13 @@ public class DigEffect extends SpellAbilityEffect {
}
if (sa.hasAdditionalAbility("AnimateSubAbility")) {
// need LKI before Animate does apply
if (!moveParams.containsKey(AbilityKey.CardLKI)) {
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(c));
}
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(c));
final SpellAbility animate = sa.getAdditionalAbility("AnimateSubAbility");
host.addRemembered(c);
AbilityUtils.resolve(sa.getAdditionalAbility("AnimateSubAbility"));
AbilityUtils.resolve(animate);
host.removeRemembered(c);
animate.setSVar("unanimateTimestamp", String.valueOf(game.getTimestamp()));
}
c = game.getAction().moveTo(zone, c, sa, moveParams);
if (destZone1.equals(ZoneType.Battlefield)) {

View File

@@ -226,7 +226,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private boolean tributed = false;
private boolean embalmed = false;
private boolean eternalized = false;
private boolean madnessWithoutCast = false;
private boolean discarded = false;
private boolean flipped = false;
private boolean facedown = false;
@@ -5801,8 +5801,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
return getCastSA().isMadness();
}
public boolean getMadnessWithoutCast() { return madnessWithoutCast; }
public void setMadnessWithoutCast(boolean state) { madnessWithoutCast = state; }
public boolean wasDiscarded() { return discarded; }
public void setDiscarded(boolean state) { discarded = state; }
public final boolean isMonstrous() {
return monstrous;

View File

@@ -984,8 +984,7 @@ public class CardProperty {
return false;
}
List<Card> cards = CardUtil.getThisTurnEntered(ZoneType.Graveyard, ZoneType.Hand, "Card", source, spellAbility);
if (!cards.contains(card) && !card.getMadnessWithoutCast()) {
if (!card.wasDiscarded()) {
return false;
}
} else if (property.startsWith("ControlledByPlayerInTheDirection")) {

View File

@@ -1444,6 +1444,9 @@ public class Player extends GameEntity implements Comparable<Player> {
newCard = game.getAction().moveToGraveyard(c, sa, params);
// Play the Discard sound
}
newCard.setDiscarded(true);
if (table != null) {
table.put(origin, newCard.getZone().getZoneType(), newCard);
}

View File

@@ -6,6 +6,7 @@ package forge.game.replacement;
*
*/
public enum ReplacementLayer {
CantHappen, // 614.17
Control, // 616.1b
Copy, // 616.1c
Transform, // 616.1d

View File

@@ -664,9 +664,9 @@ public class AbilityManaPart implements java.io.Serializable {
// check for produce mana replacement effects - they mess this up, so just use the mana ability
final Card source = am.getHostCard();
final Player activator = am.getActivatingPlayer();
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromPlayer(activator);
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(source);
repParams.put(AbilityKey.Mana, getOrigProduced());
repParams.put(AbilityKey.Affected, source);
repParams.put(AbilityKey.Activator, activator);
repParams.put(AbilityKey.AbilityMana, am.getRootAbility());
if (!source.getGame().getReplacementHandler().getReplacementList(ReplacementType.ProduceMana, repParams, ReplacementLayer.Other).isEmpty()) {

View File

@@ -79,7 +79,6 @@ public class WorldSave {
System.err.println("Generating New World");
currentSave.world.generateNew(0);
}
currentSave.pointOfInterestChanges.clear();
currentSave.onLoadList.emit();

View File

@@ -16,7 +16,7 @@ SVar:RepeatOpp:DB$ RepeatEach | RepeatSubAbility$ ChooseCardsToTap | RepeatPlaye
SVar:ChooseCardsToTap:DB$ ChooseCard | Defined$ Opponent | MinAmount$ 0 | Amount$ NumCreatures | Choices$ Creature.untapped+RememberedPlayerCtrl | ChoiceTitle$ Choose any number of untapped creatures you control | ChoiceZone$ Battlefield | RememberChosen$ True | AILogic$ BowToMyCommand | SubAbility$ TapChosenCards
SVar:TapChosenCards:DB$ Tap | Defined$ Remembered | SubAbility$ AbandonSelf | ConditionCheckSVar$ TappedCreaturePower | ConditionSVarCompare$ GE8
SVar:AbandonSelf:DB$ Abandon | SubAbility$ DBCleanup | ConditionCheckSVar$ TappedCreaturePower | ConditionSVarCompare$ GE8
T:Mode$ Abandoned | ValidCard$ Self | Execute$ DBCleanup
T:Mode$ Abandoned | ValidCard$ Card.Self | Execute$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearChosenCard$ True
SVar:NumCreatures:Count$Valid Creature.RememberedPlayerCtrl
SVar:TappedCreaturePower:Count$SumPower_Card.IsRemembered

View File

@@ -1,7 +1,7 @@
Name:Grafdigger's Cage
ManaCost:1
Types:Artifact
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Graveyard,Library | Destination$ Battlefield | ValidLKI$ Creature.Other | Prevent$ True | Description$ Creature cards in graveyards and libraries can't enter the battlefield.
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Graveyard,Library | Destination$ Battlefield | ValidLKI$ Creature.Other | Prevent$ True | Layer$ CantHappen | Description$ Creature cards in graveyards and libraries can't enter the battlefield.
S:Mode$ CantBeCast | Origin$ Graveyard,Library | Description$ Players can't cast spells from graveyards or libraries.
SVar:NonStackingEffect:True
AI:RemoveDeck:Random

View File

@@ -3,8 +3,9 @@ ManaCost:1 W B
Types:Legendary Creature Rat Pilot
PT:4/3
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ At the beginning of combat on your turn, return target Vehicle card from your graveyard to the battlefield. It gains haste. Return it to its owner's hand at the beginning of your next end step.
SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Select target Vehicle card in your graveyard | ValidTgts$ Vehicle.YouOwn | AnimateSubAbility$ Animate
SVar:Animate:DB$ Animate | Keywords$ Haste | Defined$ Remembered | Duration$ Permanent | AtEOT$ Hand
SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Select target Vehicle card in your graveyard | ValidTgts$ Vehicle.YouOwn | SubAbility$ Animate | RememberChanged$ True | AtEOT$ Hand
SVar:Animate:DB$ Animate | Keywords$ Haste | Defined$ Remembered | Duration$ Permanent | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
DeckHas:Ability$Graveyard
DeckNeeds:Type$Vehicle
Oracle:At the beginning of combat on your turn, return target Vehicle card from your graveyard to the battlefield. It gains haste. Return it to its owner's hand at the beginning of your next end step.

View File

@@ -5,7 +5,7 @@ PT:3/3
K:Vigilance
K:Menace
K:Lifelink
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Graveyard | Destination$ Battlefield | ValidLKI$ Creature.Other | Prevent$ True | Description$ Creature cards in graveyards can't enter the battlefield.
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Graveyard | Destination$ Battlefield | ValidLKI$ Creature.Other | Prevent$ True | Layer$ CantHappen | Description$ Creature cards in graveyards can't enter the battlefield.
S:Mode$ CantBeCast | Origin$ Graveyard | Description$ Players can't cast spells from graveyards.
SVar:NonStackingEffect:True
Oracle:Vigilance, menace, lifelink\nCreature cards in graveyards can't enter the battlefield.\nPlayers can't cast spells from graveyards.

View File

@@ -3,7 +3,7 @@ ManaCost:3 U
Types:Creature Faerie
PT:2/2
K:Flying
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw cards equal to the number of opponents who were dealt combat damage this turn.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw cards equal to the number of opponents who were dealt combat damage this turn.
SVar:TrigDraw:DB$ Draw | NumCards$ X
SVar:X:PlayerCountRegisteredOpponents$HasPropertywasDealtCombatDamageThisTurn
AlternateMode:Adventure

View File

@@ -5,8 +5,9 @@ PT:3/4
K:Flying
K:Haste
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChange | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, return target creature card from your graveyard to the battlefield tapped and attacking. It gains "When you don't control a legendary Vampire, exile this creature."
SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | Tapped$ True | Attacking$ True | AnimateSubAbility$ DBAnimate
SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Duration$ Permanent | Triggers$ TrigOlivia
SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | Tapped$ True | Attacking$ True | RememberChanged$ True | SubAbility$ DBAnimate
SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Duration$ Permanent | Triggers$ TrigOlivia | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:TrigOlivia:Mode$ Always | TriggerZones$ Battlefield | IsPresent$ Vampire.YouCtrl+Legendary | PresentCompare$ EQ0 | Execute$ TrigExile | TriggerDescription$ When you don't control a legendary Vampire, exile this creature.
SVar:TrigExile:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile
SVar:HasAttackEffect:TRUE

View File

@@ -2,6 +2,7 @@ Name:Swords to Plowshares
ManaCost:W
Types:Instant
A:SP$ ChangeZone | ValidTgts$ Creature | Origin$ Battlefield | Destination$ Exile | RememberLKI$ True | SubAbility$ DBGainLife | SpellDescription$ Exile target creature.
SVar:DBGainLife:DB$ GainLife | Defined$ RememberedController | LifeAmount$ X | SpellDescription$ Its controller gains life equal to its power.
SVar:DBGainLife:DB$ GainLife | Defined$ RememberedController | LifeAmount$ X | SubAbility$ DBCleanup | SpellDescription$ Its controller gains life equal to its power.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:RememberedLKI$CardPower
Oracle:Exile target creature. Its controller gains life equal to its power.

View File

@@ -1,7 +1,7 @@
Name:Weathered Runestone
ManaCost:2
Types:Artifact
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Graveyard,Library | Destination$ Battlefield | ValidLKI$ Permanent.nonland | Prevent$ True | Description$ Nonland permanent cards in graveyards and libraries can't enter the battlefield.
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Graveyard,Library | Destination$ Battlefield | ValidLKI$ Permanent.nonland | Prevent$ True | Layer$ CantHappen | Description$ Nonland permanent cards in graveyards and libraries can't enter the battlefield.
S:Mode$ CantBeCast | Origin$ Graveyard,Library | Description$ Players can't cast spells from graveyards or libraries.
SVar:NonStackingEffect:True
AI:RemoveDeck:Random

View File

@@ -2,7 +2,7 @@ Name:Worms of the Earth
ManaCost:2 B B B
Types:Enchantment
S:Mode$ CantPlayLand | Description$ Players can't play lands.
R:Event$ Moved | ActiveZones$ Battlefield | Destination$ Battlefield | ValidCard$ Land | Prevent$ True | Description$ Lands can't enter the battlefield.
R:Event$ Moved | ActiveZones$ Battlefield | Destination$ Battlefield | ValidCard$ Land | Prevent$ True | Layer$ CantHappen | Description$ Lands can't enter the battlefield.
T:Mode$ Phase | Phase$ Upkeep | TriggerZones$ Battlefield | Execute$ RepeatAbility | TriggerDescription$ At the beginning of each upkeep, any player may sacrifice two lands or have CARDNAME deal 5 damage to that player. If a player does either, destroy CARDNAME.
SVar:RepeatAbility:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBChoose
SVar:DBChoose:DB$ GenericChoice | Defined$ Player.IsRemembered | Choices$ SacTwoLands,DealDmg | AILogic$ PayUnlessCost

View File

@@ -0,0 +1,78 @@
[metadata]
name=Chaos Incarnate [SCD] [2022]
[Commander]
1 Kardur, Doomscourge|SCD|1
[Main]
1 Abrade|SCD|1
1 Akoum Refuge|SCD|1
1 Ambition's Cost|SCD|1
1 Arcane Signet|SCD|1
1 Archfiend of Depravity|SCD|1
1 Blasphemous Act|SCD|1
1 Bloodfell Caves|SCD|1
1 Bloodgift Demon|SCD|1
1 Brash Taunter|SCD|1
1 Breath of Malfegor|SCD|1
1 Burnished Hart|SCD|1
1 Chaos Warp|SCD|1
1 Cinder Barrens|SCD|1
1 Combustible Gearhulk|SCD|1
1 Command Tower|SCD|1
1 Commander's Sphere|SCD|1
1 Coveted Jewel|SCD|1
1 Deadly Tempest|SCD|1
1 Dictate of the Twin Gods|SCD|1
1 Dredge the Mire|SCD|1
1 Explosion of Riches|SCD|1
1 Feed the Swarm|SCD|1
1 Fiery Confluence|SCD|1
1 Foreboding Ruins|SCD|1
1 Geode Rager|SCD|1
1 Guttersnipe|SCD|1
1 Hate Mirage|SCD|1
1 Indulgent Tormentor|SCD|1
1 Kaervek the Merciless|SCD|1
1 Kazuul, Tyrant of the Cliffs|SCD|1
1 Lightning Greaves|SCD|1
1 Magmatic Force|SCD|1
1 Mana Geyser|SCD|1
1 Molten Slagheap|SCD|1
14 Mountain|SCD|1
1 Myriad Landscape|SCD|1
1 Nihil Spellbomb|SCD|1
1 Ob Nixilis Reignited|SCD|1
1 Profane Command|SCD|1
1 Rakdos Charm|SCD|1
1 Rakdos Signet|SCD|1
1 Rakshasa Debaser|SCD|1
1 Read the Bones|SCD|1
1 Reign of the Pit|SCD|1
1 Sangromancer|SCD|1
1 Scythe Specter|SCD|1
1 Sepulchral Primordial|SCD|1
1 Sign in Blood|SCD|1
1 Smoldering Marsh|SCD|1
1 Sol Ring|SCD|1
1 Solemn Simulacrum|SCD|1
1 Soul Shatter|SCD|1
1 Spiteful Visions|SCD|1
1 Stensia Bloodhall|SCD|1
1 Stormfist Crusader|SCD|1
1 Sunbird's Invocation|SCD|1
15 Swamp|SCD|1
1 Syphon Mind|SCD|1
1 Talisman of Indulgence|SCD|1
1 Tectonic Giant|SCD|1
1 Temple of Malice|SCD|1
1 Terminate|SCD|1
1 Theater of Horrors|SCD|1
1 Thermo-Alchemist|SCD|1
1 Titan Hunter|SCD|1
1 Unlicensed Disintegration|SCD|1
1 Urborg Volcano|SCD|1
1 Vampire Nighthawk|SCD|1
1 Wayfarer's Bauble|SCD|1
1 Wild Ricochet|SCD|1
1 Wildfire Devils|SCD|1
1 Worn Powerstone|SCD|1
[Sideboard]

View File

@@ -0,0 +1,77 @@
[metadata]
name=Draconic Destruction [SCD] [2022]
[Commander]
1 Atarka, World Render|SCD|1
[Main]
1 Akoum Hellkite|SCD|1
1 Arcane Signet|SCD|1
1 Atarka Monument|SCD|1
1 Beast Within|SCD|1
1 Blossoming Defense|SCD|1
1 Chain Reaction|SCD|1
1 Cinder Glade|SCD|1
1 Clan Defiance|SCD|1
1 Command Tower|SCD|1
1 Commander's Sphere|SCD|1
1 Crucible of Fire|SCD|1
1 Cultivate|SCD|1
1 Demanding Dragon|SCD|1
1 Draconic Disciple|SCD|1
1 Dragon Mage|SCD|1
1 Dragon Tempest|SCD|1
1 Dragon's Hoard|SCD|1
1 Dragonkin Berserker|SCD|1
1 Dragonlord's Servant|SCD|1
1 Dragonmaster Outcast|SCD|1
1 Dragonspeaker Shaman|SCD|1
1 Drakuseth, Maw of Flames|SCD|1
1 Dream Pillager|SCD|1
1 Drumhunter|SCD|1
1 Elemental Bond|SCD|1
1 Fires of Yavimaya|SCD|1
1 Flameblast Dragon|SCD|1
1 Foe-Razer Regent|SCD|1
12 Forest|SCD|1
1 Frontier Siege|SCD|1
1 Furnace Whelp|SCD|1
1 Game Trail|SCD|1
1 Garruk's Uprising|SCD|1
1 Harbinger of the Hunt|SCD|1
1 Harmonize|SCD|1
1 Haven of the Spirit Dragon|SCD|1
1 Hoard-Smelter Dragon|SCD|1
1 Hunter's Insight|SCD|1
1 Hunter's Prowess|SCD|1
1 Kazandu Refuge|SCD|1
1 Loaming Shaman|SCD|1
1 Magmaquake|SCD|1
1 Mordant Dragon|SCD|1
18 Mountain|SCD|1
1 Path of Ancestry|SCD|1
1 Primal Might|SCD|1
1 Provoke the Trolls|SCD|1
1 Rapacious Dragon|SCD|1
1 Return to Nature|SCD|1
1 Rugged Highlands|SCD|1
1 Runehorn Hellkite|SCD|1
1 Sakura-Tribe Elder|SCD|1
1 Sarkhan, the Dragonspeaker|SCD|1
1 Savage Ventmaw|SCD|1
1 Scourge of Valkas|SCD|1
1 Shamanic Revelation|SCD|1
1 Shivan Oasis|SCD|1
1 Sol Ring|SCD|1
1 Spit Flame|SCD|1
1 Steel Hellkite|SCD|1
1 Sweltering Suns|SCD|1
1 Swiftfoot Boots|SCD|1
1 Talisman of Impulse|SCD|1
1 Temple of Abandon|SCD|1
1 Thunderbreak Regent|SCD|1
1 Thundermaw Hellkite|SCD|1
1 Timber Gorge|SCD|1
1 Tyrant's Familiar|SCD|1
1 Unleash Fury|SCD|1
1 Vandalblast|SCD|1
1 Verix Bladewing|SCD|1
[Sideboard]

View File

@@ -0,0 +1,77 @@
[metadata]
name=First Flight [SCD] [2022]
[Commander]
1 Isperia, Supreme Judge|SCD|1
[Main]
1 Absorb|SCD|1
1 Aetherize|SCD|1
1 Angler Turtle|SCD|1
1 Arcane Signet|SCD|1
1 Archon of Redemption|SCD|1
1 Aven Gagglemaster|SCD|1
1 Azorius Signet|SCD|1
1 Banishing Light|SCD|1
1 Bident of Thassa|SCD|1
1 Cartographer's Hawk|SCD|1
1 Cleansing Nova|SCD|1
1 Cloudblazer|SCD|1
1 Coastal Tower|SCD|1
1 Command Tower|SCD|1
1 Commander's Sphere|SCD|1
1 Condemn|SCD|1
1 Counterspell|SCD|1
1 Crush Contraband|SCD|1
1 Diluvian Primordial|SCD|1
1 Disenchant|SCD|1
1 Emeria Angel|SCD|1
1 Empyrean Eagle|SCD|1
1 Ever-Watching Threshold|SCD|1
1 Faerie Formation|SCD|1
1 Favorable Winds|SCD|1
1 Generous Gift|SCD|1
1 Gideon Jura|SCD|1
1 Gravitational Shift|SCD|1
1 Hanged Executioner|SCD|1
1 Hedron Archive|SCD|1
1 Inspired Sphinx|SCD|1
15 Island|SCD|1
1 Jubilant Skybonder|SCD|1
1 Kangee's Lieutenant|SCD|1
1 Kangee, Sky Warden|SCD|1
1 Meandering River|SCD|1
1 Migratory Route|SCD|1
1 Moorland Haunt|SCD|1
1 Negate|SCD|1
1 Pilgrim's Eye|SCD|1
15 Plains|SCD|1
1 Port Town|SCD|1
1 Prairie Stream|SCD|1
1 Rally of Wings|SCD|1
1 Remorseful Cleric|SCD|1
1 Sejiri Refuge|SCD|1
1 Sephara, Sky's Blade|SCD|1
1 Sharding Sphinx|SCD|1
1 Sky Diamond|SCD|1
1 Skycat Sovereign|SCD|1
1 Skyscanner|SCD|1
1 Sol Ring|SCD|1
1 Soul Snare|SCD|1
1 Sphinx of Enlightenment|SCD|1
1 Sphinx's Revelation|SCD|1
1 Staggering Insight|SCD|1
1 Steel-Plume Marshal|SCD|1
1 Storm Herd|SCD|1
1 Swords to Plowshares|SCD|1
1 Talisman of Progress|SCD|1
1 Temple of Enlightenment|SCD|1
1 Thought Vessel
1 Thunderclap Wyvern|SCD|1
1 Tide Skimmer|SCD|1
1 Time Wipe|SCD|1
1 Tranquil Cove|SCD|1
1 True Conviction|SCD|1
1 Vow of Duty|SCD|1
1 Warden of Evos Isle|SCD|1
1 Windreader Sphinx|SCD|1
1 Winged Words|SCD|1
[Sideboard]

View File

@@ -0,0 +1,76 @@
[metadata]
name=Grave Danger [SCD] [2022]
[Commander]
1 Gisa and Geralf|SCD|1
[Main]
1 Arcane Signet|SCD|1
1 Army of the Damned|SCD|1
1 Cemetery Reaper|SCD|1
1 Champion of the Perished|SCD|1
1 Choked Estuary|SCD|1
1 Command Tower|SCD|1
1 Commander's Sphere|SCD|1
1 Crippling Fear|SCD|1
1 Cruel Revival|SCD|1
1 Curse of Disturbance|SCD|1
1 Deep Analysis|SCD|1
1 Dimir Signet|SCD|1
1 Diregraf Captain|SCD|1
1 Dismal Backwater|SCD|1
1 Distant Melody|SCD|1
1 Enter the God-Eternals|SCD|1
1 Eternal Skylord|SCD|1
1 Feed the Swarm|SCD|1
1 Fleshbag Marauder|SCD|1
1 Geralf's Mindcrusher|SCD|1
1 Gleaming Overseer|SCD|1
1 Gravespawn Sovereign|SCD|1
1 Gray Merchant of Asphodel|SCD|1
1 Grimoire of the Dead|SCD|1
1 Havengul Lich|SCD|1
1 Heraldic Banner|SCD|1
13 Island|SCD|1
1 Josu Vess, Lich Knight|SCD|1
1 Jwar Isle Refuge|SCD|1
1 Laboratory Drudge|SCD|1
1 Lazotep Plating|SCD|1
1 Lazotep Reaver|SCD|1
1 Liliana's Devotee|SCD|1
1 Liliana's Mastery|SCD|1
1 Liliana's Standard Bearer|SCD|1
1 Liliana, Untouched by Death|SCD|1
1 Lord of the Accursed|SCD|1
1 Lotleth Giant|SCD|1
1 Loyal Subordinate|SCD|1
1 Midnight Reaper|SCD|1
1 Mire Triton|SCD|1
1 Murder|SCD|1
1 Necromantic Selection|SCD|1
1 Necrotic Hex|SCD|1
1 Open the Graves|SCD|1
1 Overseer of the Damned|SCD|1
1 Pilfered Plans|SCD|1
1 Salt Marsh|SCD|1
1 Scourge of Nel Toth|SCD|1
1 Sinister Sabotage|SCD|1
1 Sol Ring|SCD|1
1 Spark Reaper|SCD|1
1 Submerged Boneyard|SCD|1
1 Sunken Hollow|SCD|1
18 Swamp|SCD|1
1 Syphon Flesh|SCD|1
1 Talisman of Dominance|SCD|1
1 Temple of Deceit|SCD|1
1 Unbreathing Horde|SCD|1
1 Undead Augur|SCD|1
1 Undermine|SCD|1
1 Unstable Obelisk|SCD|1
1 Vampiric Rites|SCD|1
1 Vela the Night-Clad|SCD|1
1 Vengeful Dead|SCD|1
1 Victimize|SCD|1
1 Vizier of the Scorpion|SCD|1
1 Wayfarer's Bauble|SCD|1
1 Withered Wretch|SCD|1
1 Zombie Apocalypse|SCD|1
[Sideboard]

View File

@@ -0,0 +1,78 @@
[metadata]
name=Token Triumph [SCD] [2022]
[Commander]
1 Emmara, Soul of the Accord|SCD|1
[Main]
1 Ajani, Caller of the Pride|SCD|1
1 Arcane Signet|SCD|1
1 Aura Mutation|SCD|1
1 Avacyn's Pilgrim|SCD|1
1 Blossoming Sands|SCD|1
1 Camaraderie|SCD|1
1 Canopy Vista|SCD|1
1 Champion of Lambholt|SCD|1
1 Citanul Hierophants|SCD|1
1 Citywide Bust|SCD|1
1 Collective Blessing|SCD|1
1 Collective Unconscious|SCD|1
1 Command Tower|SCD|1
1 Commander's Insignia|SCD|1
1 Commander's Sphere|SCD|1
1 Conclave Tribunal|SCD|1
1 Curse of Bounty|SCD|1
1 Dauntless Escort|SCD|1
1 Dawn of Hope|SCD|1
1 Devouring Light|SCD|1
1 Dictate of Heliod|SCD|1
1 Elfhame Palace|SCD|1
1 Eternal Witness|SCD|1
1 Farhaven Elf|SCD|1
1 Felidar Retreat|SCD|1
15 Forest|SCD|1
1 Fortified Village|SCD|1
1 Graypelt Refuge|SCD|1
1 Great Oak Guardian|SCD|1
1 Harmonize|SCD|1
1 Harvest Season|SCD|1
1 Holdout Settlement|SCD|1
1 Hornet Nest|SCD|1
1 Hornet Queen|SCD|1
1 Hour of Reckoning|SCD|1
1 Idol of Oblivion|SCD|1
1 Jade Mage|SCD|1
1 Jaspera Sentinel|SCD|1
1 Karametra's Favor|SCD|1
1 Leafkin Druid|SCD|1
1 Loyal Guardian|SCD|1
1 Maja, Bretagard Protector|SCD|1
1 March of the Multitudes|SCD|1
1 Mentor of the Meek|SCD|1
1 Nissa's Expedition|SCD|1
1 Nullmage Shepherd|SCD|1
1 Overrun|SCD|1
1 Overwhelming Instinct|SCD|1
1 Path to Exile|SCD|1
14 Plains|SCD|1
1 Presence of Gond|SCD|1
1 Reclamation Sage|SCD|1
1 Rishkar, Peema Renegade|SCD|1
1 Rootborn Defenses|SCD|1
1 Scatter the Seeds|SCD|1
1 Scavenging Ooze|SCD|1
1 Selesnya Evangel|SCD|1
1 Selesnya Guildmage|SCD|1
1 Slate of Ancestry|SCD|1
1 Sol Ring|SCD|1
1 Sporemound|SCD|1
1 Sylvan Reclamation|SCD|1
1 Talisman of Unity|SCD|1
1 Temple of Plenty|SCD|1
1 Thunderfoot Baloth|SCD|1
1 Tranquil Expanse|SCD|1
1 Trostani Discordant|SCD|1
1 Valor in Akros|SCD|1
1 Verdant Force|SCD|1
1 Vitu-Ghazi, the City-Tree|SCD|1
1 Voice of Many|SCD|1
1 White Sun's Zenith|SCD|1
[Sideboard]

View File

@@ -114,9 +114,11 @@ public class HumanPlay {
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
if (!req.playAbility(true, false, false)) {
if (flippedToCast && !castFaceDown) {
Card rollback = p.getGame().getCardState(sa.getHostCard());
if (castFaceDown) {
rollback.setFaceDown(false);
} else if (flippedToCast) {
// need to get the changed card if able
Card rollback = p.getGame().getCardState(sa.getHostCard());
rollback.turnFaceDown(true);
//need to set correct imagekey when forcing facedown
rollback.setImageKey(ImageKeys.getTokenKey(isforetold ? ImageKeys.FORETELL_IMAGE : ImageKeys.HIDDEN_CARD));

View File

@@ -173,7 +173,7 @@ public class HumanPlaySpellAbility {
if (ability.getHostCard().isMadness()) {
// if a player failed to play madness cost, move the card to graveyard
Card newCard = game.getAction().moveToGraveyard(c, null);
newCard.setMadnessWithoutCast(true);
newCard.setDiscarded(true);
}
} else {
payment.refundPayment();