mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 02:08:00 +00:00
Merge remote-tracking branch 'upstream/master' into editions-type-review
This commit is contained in:
@@ -11,6 +11,7 @@ import forge.game.mana.ManaCostBeingPaid;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
|
|
||||||
public class ForgeScript {
|
public class ForgeScript {
|
||||||
@@ -122,7 +123,6 @@ public class ForgeScript {
|
|||||||
return Expressions.compare(y, property, x);
|
return Expressions.compare(y, property, x);
|
||||||
} else return cardState.getTypeWithChanges().hasStringType(property);
|
} else return cardState.getTypeWithChanges().hasStringType(property);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean spellAbilityHasProperty(SpellAbility sa, String property, Player sourceController,
|
public static boolean spellAbilityHasProperty(SpellAbility sa, String property, Player sourceController,
|
||||||
@@ -187,7 +187,14 @@ public class ForgeScript {
|
|||||||
} else if (property.equals("OppCtrl")) {
|
} else if (property.equals("OppCtrl")) {
|
||||||
return sa.getActivatingPlayer().isOpponentOf(sourceController);
|
return sa.getActivatingPlayer().isOpponentOf(sourceController);
|
||||||
} else if (property.startsWith("cmc")) {
|
} else if (property.startsWith("cmc")) {
|
||||||
int y = sa.getPayCosts().getTotalMana().getCMC();
|
int y = 0;
|
||||||
|
// spell was on the stack
|
||||||
|
if (sa.getCardState().getCard().isInZone(ZoneType.Stack)) {
|
||||||
|
y = sa.getHostCard().getCMC();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
y = sa.getPayCosts().getTotalMana().getCMC();
|
||||||
|
}
|
||||||
int x = AbilityUtils.calculateAmount(spellAbility.getHostCard(), property.substring(5), spellAbility);
|
int x = AbilityUtils.calculateAmount(spellAbility.getHostCard(), property.substring(5), spellAbility);
|
||||||
if (!Expressions.compare(y, property, x)) {
|
if (!Expressions.compare(y, property, x)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -329,7 +329,6 @@ public abstract class SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static void addSelfTrigger(final SpellAbility sa, String location, final Card card) {
|
protected static void addSelfTrigger(final SpellAbility sa, String location, final Card card) {
|
||||||
|
|
||||||
String trigStr = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield " +
|
String trigStr = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield " +
|
||||||
"| TriggerDescription$ At the beginning of the end step, " + location.toLowerCase() + " CARDNAME.";
|
"| TriggerDescription$ At the beginning of the end step, " + location.toLowerCase() + " CARDNAME.";
|
||||||
|
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ public class DamageDealEffect extends DamageBaseEffect {
|
|||||||
// if use targeting we show all targets and corresponding damage
|
// if use targeting we show all targets and corresponding damage
|
||||||
if (spellAbility.usesTargeting()) {
|
if (spellAbility.usesTargeting()) {
|
||||||
if (spellAbility.hasParam("DivideEvenly")) {
|
if (spellAbility.hasParam("DivideEvenly")) {
|
||||||
stringBuilder.append("divided evenly (rounded down) to\n");
|
stringBuilder.append("divided evenly (rounded down) to \n");
|
||||||
} else if (spellAbility.isDividedAsYouChoose()) {
|
} else if (spellAbility.isDividedAsYouChoose()) {
|
||||||
stringBuilder.append("divided to\n");
|
stringBuilder.append("divided to \n");
|
||||||
} else
|
} else
|
||||||
stringBuilder.append("to ");
|
stringBuilder.append("to ");
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ public class DestroyAllEffect extends SpellAbilityEffect {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
|
|
||||||
final boolean noRegen = sa.hasParam("NoRegen");
|
final boolean noRegen = sa.hasParam("NoRegen");
|
||||||
final Card card = sa.getHostCard();
|
final Card card = sa.getHostCard();
|
||||||
final Game game = sa.getActivatingPlayer().getGame();
|
final Game game = sa.getActivatingPlayer().getGame();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public class ETBReplacementEffect extends SpellAbilityEffect {
|
|||||||
Map<AbilityKey, Object> params = AbilityKey.newMap();
|
Map<AbilityKey, Object> params = AbilityKey.newMap();
|
||||||
params.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
|
params.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
|
||||||
params.put(AbilityKey.ReplacementEffect, sa.getReplacementEffect());
|
params.put(AbilityKey.ReplacementEffect, sa.getReplacementEffect());
|
||||||
sa.getActivatingPlayer().getGame().getAction().moveToPlay(card, card.getController(), sa, params);
|
final SpellAbility root = sa.getRootAbility();
|
||||||
|
SpellAbility cause = (SpellAbility) root.getReplacingObject(AbilityKey.Cause);
|
||||||
|
sa.getActivatingPlayer().getGame().getAction().moveToPlay(card, card.getController(), cause, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,6 @@ public class PumpEffect extends SpellAbilityEffect {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected String getStackDescription(final SpellAbility sa) {
|
protected String getStackDescription(final SpellAbility sa) {
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
List<GameEntity> tgts = Lists.newArrayList();
|
List<GameEntity> tgts = Lists.newArrayList();
|
||||||
tgts.addAll(getCardsfromTargets(sa));
|
tgts.addAll(getCardsfromTargets(sa));
|
||||||
|
|||||||
@@ -1262,8 +1262,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final int getXManaCostPaid() {
|
public final int getXManaCostPaid() {
|
||||||
if (getCastSA() != null) {
|
SpellAbility castSA;
|
||||||
Integer paid = getCastSA().getXManaCostPaid();
|
if (getCopiedPermanent() != null) {
|
||||||
|
castSA = getCopiedPermanent().getCastSA();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
castSA = getCastSA();
|
||||||
|
}
|
||||||
|
if (castSA != null) {
|
||||||
|
Integer paid = castSA.getXManaCostPaid();
|
||||||
return paid == null ? 0 : paid;
|
return paid == null ? 0 : paid;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -534,7 +534,6 @@ public class CardFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host, final Player p, final boolean lki) {
|
public static void copySpellAbility(SpellAbility from, SpellAbility to, final Card host, final Player p, final boolean lki) {
|
||||||
|
|
||||||
if (from.getTargetRestrictions() != null) {
|
if (from.getTargetRestrictions() != null) {
|
||||||
to.setTargetRestrictions(from.getTargetRestrictions());
|
to.setTargetRestrictions(from.getTargetRestrictions());
|
||||||
}
|
}
|
||||||
@@ -562,7 +561,7 @@ public class CardFactory {
|
|||||||
to.setConditions((SpellAbilityCondition) from.getConditions().copy());
|
to.setConditions((SpellAbilityCondition) from.getConditions().copy());
|
||||||
}
|
}
|
||||||
|
|
||||||
// do this after other abilties are copied
|
// do this after other abilities are copied
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
to.setActivatingPlayer(p, lki);
|
to.setActivatingPlayer(p, lki);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
|||||||
private Keyword keyword;
|
private Keyword keyword;
|
||||||
private String original;
|
private String original;
|
||||||
|
|
||||||
|
|
||||||
private boolean hidden;
|
private boolean hidden;
|
||||||
|
|
||||||
private List<Trigger> triggers = Lists.newArrayList();
|
private List<Trigger> triggers = Lists.newArrayList();
|
||||||
@@ -206,8 +205,6 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
|||||||
staticAbilities.add(st);
|
staticAbilities.add(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.game.keyword.KeywordInterface#getHidden()
|
* @see forge.game.keyword.KeywordInterface#getHidden()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -960,7 +960,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
return this.isAlternativeCost(AlternativeCost.Foretold);
|
return this.isAlternativeCost(AlternativeCost.Foretold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the aftermath
|
* @return the aftermath
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
|
|||||||
ability.resetPaidHash();
|
ability.resetPaidHash();
|
||||||
splicedCards = sa.getSplicedCards();
|
splicedCards = sa.getSplicedCards();
|
||||||
|
|
||||||
// TODO getXManaCostPaid should be on the SA, not the Card
|
|
||||||
xManaPaid = sa.getXManaCostPaid();
|
xManaPaid = sa.getXManaCostPaid();
|
||||||
|
|
||||||
// Triggering info
|
// Triggering info
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ ManaCost:4 U U
|
|||||||
Types:Creature Human Soldier
|
Types:Creature Human Soldier
|
||||||
PT:4/3
|
PT:4/3
|
||||||
K:Flying
|
K:Flying
|
||||||
A:AB$ Dig | Cost$ 1 U U | Defined$ You | DigNum$ 1 | Destination$ Exile | RememberChanged$ True | SubAbility$ DBEffect | AILogic$ ExileAndPlayUntilEOT | SpellDescription$ Exile the top card of your library. Until end of turn, you may play that card. (Reveal the card as you exile it.)
|
A:AB$ Dig | Cost$ 1 U U | Defined$ You | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | AILogic$ ExileAndPlayUntilEOT | SpellDescription$ Exile the top card of your library. Until end of turn, you may play that card. (Reveal the card as you exile it.)
|
||||||
SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ Play | SubAbility$ DBCleanup | ExileOnMoved$ Exile
|
SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ Play | SubAbility$ DBCleanup | ExileOnMoved$ Exile
|
||||||
SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play remembered card.
|
SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play remembered card.
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/aerial_caravan.jpg
|
|
||||||
Oracle:Flying\n{1}{U}{U}: Exile the top card of your library. Until end of turn, you may play that card. (Reveal the card as you exile it.)
|
Oracle:Flying\n{1}{U}{U}: Exile the top card of your library. Until end of turn, you may play that card. (Reveal the card as you exile it.)
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ Types:Legendary Creature Human Wizard
|
|||||||
PT:3/3
|
PT:3/3
|
||||||
T:Mode$ SpellCastOrCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Magecraft — Whenever you cast or copy an instant or sorcery spell, create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it, where X is that spell's mana value.
|
T:Mode$ SpellCastOrCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Magecraft — Whenever you cast or copy an instant or sorcery spell, create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it, where X is that spell's mana value.
|
||||||
SVar:TrigToken:DB$ Token | TokenScript$ gu_0_0_fractal | RememberTokens$ True | SubAbility$ DBPutCounter
|
SVar:TrigToken:DB$ Token | TokenScript$ gu_0_0_fractal | RememberTokens$ True | SubAbility$ DBPutCounter
|
||||||
SVar:DBPutCounter:DB$ PutCounter | Defined$ Remembered | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBCleanup
|
SVar:DBPutCounter:DB$ PutCounter | Defined$ Remembered | CounterType$ P1P1 | CounterNum$ TriggerCount$CastSACMC | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:X:TriggerCount$CastSACMC
|
|
||||||
A:AB$ Pump | Cost$ 3 U | KW$ HIDDEN Unblockable | TgtPrompt$ Select target creature token | ValidTgts$ Creature.token | SpellDescription$ Target creature token can't be blocked this turn.
|
A:AB$ Pump | Cost$ 3 U | KW$ HIDDEN Unblockable | TgtPrompt$ Select target creature token | ValidTgts$ Creature.token | SpellDescription$ Target creature token can't be blocked this turn.
|
||||||
DeckHas:Ability$Token & Ability$Counters
|
DeckHas:Ability$Token & Ability$Counters
|
||||||
DeckNeeds:Type$Instant|Sorcery
|
DeckNeeds:Type$Instant|Sorcery
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ SVar:X:PlayerCountOpponents$Amount
|
|||||||
SVar:PlayMain1:TRUE
|
SVar:PlayMain1:TRUE
|
||||||
DeckHas:Ability$Token & Ability$LifeGain & Ability$Food & Ability$Sacrifice
|
DeckHas:Ability$Token & Ability$LifeGain & Ability$Food & Ability$Sacrifice
|
||||||
SVar:AIPreference:SacCost$Card.Food,Card.token,Card.cmcEQ1,Card.cmcEQ2
|
SVar:AIPreference:SacCost$Card.Food,Card.token,Card.cmcEQ1,Card.cmcEQ2
|
||||||
A:AB$ Pump | Cost$ 1 G Sac<1/Permanent.Other/another nonland permanent> | Defined$ Self | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ CARDNAME gets +2/+2 until end of turn.
|
A:AB$ Pump | Cost$ 1 G Sac<1/Permanent.Other+nonLand/another nonland permanent> | Defined$ Self | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ CARDNAME gets +2/+2 until end of turn.
|
||||||
Oracle:Trample\nWhen Gluttonous Troll enters the battlefield, create a number of Food tokens equal to the number of opponents you have. (Food tokens are artifacts with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")\n{1}{G}, Sacrifice another nonland permanent: Gluttonous Troll gets +2/+2 until end of turn.
|
Oracle:Trample\nWhen Gluttonous Troll enters the battlefield, create a number of Food tokens equal to the number of opponents you have. (Food tokens are artifacts with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")\n{1}{G}, Sacrifice another nonland permanent: Gluttonous Troll gets +2/+2 until end of turn.
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ Types:Creature Human Shaman
|
|||||||
PT:2/2
|
PT:2/2
|
||||||
T:Mode$ SpellCastOrCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Magecraft — Whenever you cast or copy an instant or sorcery spell, CARDNAME can't be blocked this turn. If that spell has mana value 5 or greater, put a +1/+1 counter on CARDNAME.
|
T:Mode$ SpellCastOrCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Magecraft — Whenever you cast or copy an instant or sorcery spell, CARDNAME can't be blocked this turn. If that spell has mana value 5 or greater, put a +1/+1 counter on CARDNAME.
|
||||||
SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ HIDDEN Unblockable | SubAbility$ DBPutCounter
|
SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ HIDDEN Unblockable | SubAbility$ DBPutCounter
|
||||||
SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE5
|
SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ TriggerCount$CastSACMC | ConditionSVarCompare$ GE5
|
||||||
DeckNeeds:Type$Instant|Sorcery
|
DeckNeeds:Type$Instant|Sorcery
|
||||||
DeckHas:Ability$Counters
|
DeckHas:Ability$Counters
|
||||||
SVar:X:TriggeredCard$CardManaCost
|
|
||||||
Oracle:Magecraft — Whenever you cast or copy an instant or sorcery spell, Prismari Apprentice can't be blocked this turn. If that spell has mana value 5 or greater, put a +1/+1 counter on Prismari Apprentice.
|
Oracle:Magecraft — Whenever you cast or copy an instant or sorcery spell, Prismari Apprentice can't be blocked this turn. If that spell has mana value 5 or greater, put a +1/+1 counter on Prismari Apprentice.
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ Name:Zaffai, Thunder Conductor
|
|||||||
ManaCost:2 U R
|
ManaCost:2 U R
|
||||||
Types:Legendary Creature Human Shaman
|
Types:Legendary Creature Human Shaman
|
||||||
PT:1/4
|
PT:1/4
|
||||||
T:Mode$ SpellCastOrCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ DBScry | TriggerDescription$ Magecraft — Whenever you cast or copy an instant or sorcery spell, scry 1. If that spell's mana value is 5 or greater, create a 4/4 blue and red Elemental creature token. If that spell's mana value is 10 ore greater, CARDNAME deals 10 damage to an opponent chosen at random.
|
T:Mode$ SpellCastOrCopy | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ DBScry | TriggerDescription$ Magecraft — Whenever you cast or copy an instant or sorcery spell, scry 1. If that spell's mana value is 5 or greater, create a 4/4 blue and red Elemental creature token. If that spell's mana value is 10 or greater, CARDNAME deals 10 damage to an opponent chosen at random.
|
||||||
SVar:DBScry:DB$ Scry | ScryNum$ 1 | SubAbility$ DBToken
|
SVar:DBScry:DB$ Scry | ScryNum$ 1 | SubAbility$ DBToken
|
||||||
SVar:DBToken:DB$ Token | TokenScript$ ur_4_4_elemental | TokenOwner$ You | ConditionPresent$ Card.cmcGE5 | ConditionDefined$ TriggeredCard | ConditionCompare$ GE1 | SubAbility$ DBChoose
|
SVar:DBToken:DB$ Token | TokenScript$ ur_4_4_elemental | TokenOwner$ You | ConditionCheckSVar$ TriggerCount$CastSACMC | ConditionSVarCompare$ GE5 | SubAbility$ DBChoose
|
||||||
SVar:DBChoose:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | Random$ True | SubAbility$ DBDamage
|
SVar:DBChoose:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | Random$ True | SubAbility$ DBDamage
|
||||||
SVar:DBDamage:DB$ DealDamage | NumDmg$ 10 | Defined$ ChosenPlayer | ConditionPresent$ Card.cmcGE10 | ConditionDefined$ TriggeredCard | ConditionCompare$ GE1
|
SVar:DBDamage:DB$ DealDamage | NumDmg$ 10 | Defined$ ChosenPlayer | ConditionCheckSVar$ TriggerCount$CastSACMC | ConditionSVarCompare$ GE10
|
||||||
DeckHas:Ability$Token
|
DeckHas:Ability$Token
|
||||||
SVar:BuffedBy:Instant,Sorcery
|
SVar:BuffedBy:Instant,Sorcery
|
||||||
DeckHints:Type$Instant|Sorcery
|
DeckHints:Type$Instant|Sorcery
|
||||||
|
|||||||
Reference in New Issue
Block a user