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.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Expressions;
|
||||
|
||||
public class ForgeScript {
|
||||
@@ -122,7 +123,6 @@ public class ForgeScript {
|
||||
return Expressions.compare(y, property, x);
|
||||
} else return cardState.getTypeWithChanges().hasStringType(property);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static boolean spellAbilityHasProperty(SpellAbility sa, String property, Player sourceController,
|
||||
@@ -187,7 +187,14 @@ public class ForgeScript {
|
||||
} else if (property.equals("OppCtrl")) {
|
||||
return sa.getActivatingPlayer().isOpponentOf(sourceController);
|
||||
} 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);
|
||||
if (!Expressions.compare(y, property, x)) {
|
||||
return false;
|
||||
|
||||
@@ -329,7 +329,6 @@ public abstract class SpellAbilityEffect {
|
||||
}
|
||||
|
||||
protected static void addSelfTrigger(final SpellAbility sa, String location, final Card card) {
|
||||
|
||||
String trigStr = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield " +
|
||||
"| 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 (spellAbility.usesTargeting()) {
|
||||
if (spellAbility.hasParam("DivideEvenly")) {
|
||||
stringBuilder.append("divided evenly (rounded down) to\n");
|
||||
stringBuilder.append("divided evenly (rounded down) to \n");
|
||||
} else if (spellAbility.isDividedAsYouChoose()) {
|
||||
stringBuilder.append("divided to\n");
|
||||
stringBuilder.append("divided to \n");
|
||||
} else
|
||||
stringBuilder.append("to ");
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ public class DestroyAllEffect extends SpellAbilityEffect {
|
||||
*/
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
|
||||
final boolean noRegen = sa.hasParam("NoRegen");
|
||||
final Card card = sa.getHostCard();
|
||||
final Game game = sa.getActivatingPlayer().getGame();
|
||||
|
||||
@@ -18,6 +18,8 @@ public class ETBReplacementEffect extends SpellAbilityEffect {
|
||||
Map<AbilityKey, Object> params = AbilityKey.newMap();
|
||||
params.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
|
||||
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
|
||||
protected String getStackDescription(final SpellAbility sa) {
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
List<GameEntity> tgts = Lists.newArrayList();
|
||||
tgts.addAll(getCardsfromTargets(sa));
|
||||
|
||||
@@ -1262,8 +1262,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
|
||||
public final int getXManaCostPaid() {
|
||||
if (getCastSA() != null) {
|
||||
Integer paid = getCastSA().getXManaCostPaid();
|
||||
SpellAbility castSA;
|
||||
if (getCopiedPermanent() != null) {
|
||||
castSA = getCopiedPermanent().getCastSA();
|
||||
}
|
||||
else {
|
||||
castSA = getCastSA();
|
||||
}
|
||||
if (castSA != null) {
|
||||
Integer paid = castSA.getXManaCostPaid();
|
||||
return paid == null ? 0 : paid;
|
||||
}
|
||||
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) {
|
||||
|
||||
if (from.getTargetRestrictions() != null) {
|
||||
to.setTargetRestrictions(from.getTargetRestrictions());
|
||||
}
|
||||
@@ -562,7 +561,7 @@ public class CardFactory {
|
||||
to.setConditions((SpellAbilityCondition) from.getConditions().copy());
|
||||
}
|
||||
|
||||
// do this after other abilties are copied
|
||||
// do this after other abilities are copied
|
||||
if (p != null) {
|
||||
to.setActivatingPlayer(p, lki);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,9 @@ import io.sentry.event.BreadcrumbBuilder;
|
||||
public abstract class KeywordInstance<T extends KeywordInstance<?>> implements KeywordInterface {
|
||||
private Keyword keyword;
|
||||
private String original;
|
||||
|
||||
|
||||
|
||||
private boolean hidden;
|
||||
|
||||
|
||||
private List<Trigger> triggers = Lists.newArrayList();
|
||||
private List<ReplacementEffect> replacements = Lists.newArrayList();
|
||||
private List<SpellAbility> abilities = Lists.newArrayList();
|
||||
@@ -53,7 +52,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
public String getReminderText() {
|
||||
String result = formatReminderText(keyword.reminderText);
|
||||
Matcher m = Pattern.compile("\\{(\\w):(.+?)\\}").matcher(result);
|
||||
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (m.find()) {
|
||||
m.appendReplacement(sb, Lang.nounWithNumeral(m.group(1), m.group(2)));
|
||||
@@ -75,7 +74,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
}
|
||||
protected abstract void parse(String details);
|
||||
protected abstract String formatReminderText(String reminderText);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -181,7 +180,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
public final void addTrigger(final Trigger trg) {
|
||||
triggers.add(trg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see forge.game.keyword.KeywordInterface#addReplacement(forge.game.replacement.ReplacementEffect)
|
||||
@@ -197,7 +196,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
public final void addSpellAbility(final SpellAbility s) {
|
||||
abilities.add(s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see forge.game.keyword.KeywordInterface#addStaticAbility(forge.game.staticability.StaticAbility)
|
||||
@@ -205,9 +204,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
public final void addStaticAbility(final StaticAbility st) {
|
||||
staticAbilities.add(st);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.keyword.KeywordInterface#getHidden()
|
||||
*/
|
||||
@@ -222,7 +219,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
|
||||
public void setHidden(boolean val) {
|
||||
hidden = val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see forge.game.keyword.KeywordInterface#getTriggers()
|
||||
|
||||
@@ -960,7 +960,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
return this.isAlternativeCost(AlternativeCost.Foretold);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the aftermath
|
||||
*/
|
||||
|
||||
@@ -111,7 +111,6 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
|
||||
ability.resetPaidHash();
|
||||
splicedCards = sa.getSplicedCards();
|
||||
|
||||
// TODO getXManaCostPaid should be on the SA, not the Card
|
||||
xManaPaid = sa.getXManaCostPaid();
|
||||
|
||||
// Triggering info
|
||||
|
||||
@@ -3,9 +3,8 @@ ManaCost:4 U U
|
||||
Types:Creature Human Soldier
|
||||
PT:4/3
|
||||
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: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: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.)
|
||||
|
||||
@@ -4,9 +4,8 @@ Types:Legendary Creature Human Wizard
|
||||
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.
|
||||
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: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.
|
||||
DeckHas:Ability$Token & Ability$Counters
|
||||
DeckNeeds:Type$Instant|Sorcery
|
||||
|
||||
@@ -9,5 +9,5 @@ SVar:X:PlayerCountOpponents$Amount
|
||||
SVar:PlayMain1:TRUE
|
||||
DeckHas:Ability$Token & Ability$LifeGain & Ability$Food & Ability$Sacrifice
|
||||
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.
|
||||
|
||||
@@ -4,8 +4,7 @@ Types:Creature Human Shaman
|
||||
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.
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -2,11 +2,11 @@ Name:Zaffai, Thunder Conductor
|
||||
ManaCost:2 U R
|
||||
Types:Legendary Creature Human Shaman
|
||||
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: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: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
|
||||
SVar:BuffedBy:Instant,Sorcery
|
||||
DeckHints:Type$Instant|Sorcery
|
||||
|
||||
Reference in New Issue
Block a user