mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
@@ -153,6 +153,8 @@ public class ForgeScript {
|
||||
} else if (property.equals("hasTapCost")) {
|
||||
Cost cost = sa.getPayCosts();
|
||||
return cost != null && cost.hasTapCost();
|
||||
} else if (property.equals("Blitz")) {
|
||||
return sa.isBlitz();
|
||||
} else if (property.equals("Buyback")) {
|
||||
return sa.isBuyBackAbility();
|
||||
} else if (property.equals("Cycling")) {
|
||||
|
||||
@@ -234,10 +234,10 @@ public class GameAction {
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the temporary Dash SVar when the Dashed card leaves the battlefield
|
||||
// Clean up the temporary Dash/Blitz SVar when the card leaves the battlefield
|
||||
// Clean up the temporary AtEOT SVar
|
||||
String endofTurn = c.getSVar("EndOfTurnLeavePlay");
|
||||
if (fromBattlefield && (endofTurn.equals("Dash") || endofTurn.equals("AtEOT"))) {
|
||||
if (fromBattlefield && (endofTurn.equals("Dash") || endofTurn.equals("Blitz") || endofTurn.equals("AtEOT"))) {
|
||||
c.removeSVar("EndOfTurnLeavePlay");
|
||||
}
|
||||
|
||||
|
||||
@@ -44,18 +44,40 @@ public class CopyPermanentEffect extends TokenEffectBase {
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
final Player activator = sa.getActivatingPlayer();
|
||||
final List<Card> tgtCards = getTargetCards(sa);
|
||||
boolean justOne = tgtCards.size() == 1;
|
||||
boolean addKWs = sa.hasParam("AddKeywords");
|
||||
final int numCopies = sa.hasParam("NumCopies") ?
|
||||
AbilityUtils.calculateAmount(host, sa.getParam("NumCopies"), sa) : 1;
|
||||
|
||||
sb.append("Copy ");
|
||||
sb.append(activator).append(" creates ").append(Lang.nounWithNumeralExceptOne(numCopies, "token");
|
||||
sb.append(numCopies == 1 ? " that's a copy" : " that are copies").append(" of ");
|
||||
sb.append(Lang.joinHomogenous(tgtCards));
|
||||
if (sa.hasParam("AddKeywords")) {
|
||||
|
||||
if (addKWs) {
|
||||
final List<String> keywords = Lists.newArrayList();
|
||||
keywords.addAll(Arrays.asList(sa.getParam("AddKeywords").split(" & ")));
|
||||
if (sa.getDescription().contains("except")) {
|
||||
sb.append(", except ").append(justOne ? "it has " : "they have ");
|
||||
} else {
|
||||
sb.append(". ").append(justOne ? "It gains " : "They gain ");
|
||||
}
|
||||
sb.append(Lang.joinHomogenous(keywords).toLowerCase());
|
||||
}
|
||||
|
||||
if (sa.hasParam("AddTriggers")) {
|
||||
final String oDesc = sa.getDescription();
|
||||
final String trigStg = oDesc.substring(oDesc.indexOf("\""),oDesc.lastIndexOf("\"") + 1);
|
||||
if (addKWs) {
|
||||
sb.append(" and ").append(trigStg);
|
||||
} else {
|
||||
sb.append(". ").append(justOne ? "It gains " : "They gain ").append(trigStg);
|
||||
}
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
|
||||
if (sa.hasParam("AtEOT")) {
|
||||
String atEOT = sa.getParam("AtEOT");
|
||||
String verb = "Sacrifice ";
|
||||
|
||||
@@ -45,6 +45,11 @@ public class PermanentEffect extends SpellAbilityEffect {
|
||||
c.setSVar("EndOfTurnLeavePlay", "Dash");
|
||||
registerDelayedTrigger(sa, "Hand", Lists.newArrayList(c));
|
||||
}
|
||||
// similar for Blitz keyword
|
||||
if (sa.isBlitz() && c.isInPlay()) {
|
||||
c.setSVar("EndOfTurnLeavePlay", "Blitz");
|
||||
registerDelayedTrigger(sa, "Sacrifice", Lists.newArrayList(c));
|
||||
}
|
||||
|
||||
ZoneType newZone = c.getZone().getZoneType();
|
||||
if (newZone != previousZone) {
|
||||
|
||||
@@ -2160,7 +2160,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
|| keyword.startsWith("Transfigure") || keyword.startsWith("Aura swap")
|
||||
|| keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling")
|
||||
|| keyword.startsWith("Encore") || keyword.startsWith("Mutate") || keyword.startsWith("Dungeon")
|
||||
|| keyword.startsWith("Class") || keyword.startsWith("Saga")) {
|
||||
|| keyword.startsWith("Class") || keyword.startsWith("Saga") || keyword.startsWith("Blitz")) {
|
||||
// keyword parsing takes care of adding a proper description
|
||||
} else if (keyword.equals("Unblockable")) {
|
||||
sbLong.append(getName()).append(" can't be blocked.\r\n");
|
||||
|
||||
@@ -2706,6 +2706,26 @@ public class CardFactoryUtil {
|
||||
sa.setAlternativeCost(AlternativeCost.Bestow);
|
||||
sa.setIntrinsic(intrinsic);
|
||||
inst.addSpellAbility(sa);
|
||||
} else if (keyword.startsWith("Blitz")) {
|
||||
final String[] k = keyword.split(":");
|
||||
final Cost blitzCost = new Cost(k[1], false);
|
||||
|
||||
final SpellAbility newSA = card.getFirstSpellAbility().copyWithDefinedCost(blitzCost);
|
||||
|
||||
final StringBuilder desc = new StringBuilder();
|
||||
desc.append("Blitz ").append(blitzCost.toSimpleString()).append(" (");
|
||||
desc.append(inst.getReminderText());
|
||||
desc.append(")");
|
||||
|
||||
newSA.setDescription(desc.toString());
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(card.getName()).append(" (Blitz)");
|
||||
newSA.setStackDescription(sb.toString());
|
||||
|
||||
newSA.setAlternativeCost(AlternativeCost.Blitz);
|
||||
newSA.setIntrinsic(intrinsic);
|
||||
inst.addSpellAbility(newSA);
|
||||
} else if (keyword.startsWith("Class")) {
|
||||
final String[] k = keyword.split(":");
|
||||
final int level = Integer.valueOf(k[1]);
|
||||
@@ -3455,6 +3475,18 @@ public class CardFactoryUtil {
|
||||
StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic);
|
||||
|
||||
st.setSVar("AffinityX", "Count$Valid " + t + ".YouCtrl");
|
||||
inst.addStaticAbility(st);
|
||||
} else if (keyword.startsWith("Blitz")) {
|
||||
String effect = "Mode$ Continuous | Affected$ Card.Self+blitzed | AddKeyword$ Haste | AddTrigger$ Dies";
|
||||
String trig = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | " +
|
||||
"Execute$ TrigDraw | TriggerDescription$ When this creature dies, draw a card.";
|
||||
String ab = "DB$ Draw | NumCards$ 1";
|
||||
|
||||
StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic);
|
||||
|
||||
st.setSVar("Dies", trig);
|
||||
st.setSVar("TrigDraw", ab);
|
||||
|
||||
inst.addStaticAbility(st);
|
||||
} else if (keyword.equals("Changeling")) {
|
||||
String effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" +
|
||||
|
||||
@@ -1684,6 +1684,11 @@ public class CardProperty {
|
||||
return false;
|
||||
}
|
||||
return card.getCastSA().isSurged();
|
||||
} else if (property.equals("blitzed")) {
|
||||
if (card.getCastSA() == null) {
|
||||
return false;
|
||||
}
|
||||
return card.getCastSA().isBlitz();
|
||||
} else if (property.equals("dashed")) {
|
||||
if (card.getCastSA() == null) {
|
||||
return false;
|
||||
|
||||
@@ -31,6 +31,7 @@ public enum Keyword {
|
||||
BANDING("Banding", SimpleKeyword.class, true, "Any creatures with banding, and up to one without, can attack in a band. Bands are blocked as a group. If any creatures with banding you control are blocking or being blocked by a creature, you divide that creature's combat damage, not its controller, among any of the creatures it's being blocked by or is blocking."),
|
||||
BATTLE_CRY("Battle cry", SimpleKeyword.class, false, "Whenever this creature attacks, each other attacking creature gets +1/+0 until end of turn."),
|
||||
BESTOW("Bestow", KeywordWithCost.class, false, "If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature."),
|
||||
BLITZ("Blitz", KeywordWithCost.class, false, "If you cast this spell for its blitz cost, it gains haste and \"When this creature dies, draw a card.\" Sacrifice it at the beginning of the next end step."),
|
||||
BLOODTHIRST("Bloodthirst", KeywordWithAmount.class, false, "If an opponent was dealt damage this turn, this creature enters the battlefield with {%d:+1/+1 counter} on it."),
|
||||
BUSHIDO("Bushido", KeywordWithAmount.class, false, "Whenever this creature blocks or becomes blocked, it gets +%1$d/+%1$d until end of turn."),
|
||||
BUYBACK("Buyback", KeywordWithCost.class, false, "You may pay an additional %s as you cast this spell. If you do, put it into your hand instead of your graveyard as it resolves."),
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.game.spellability;
|
||||
public enum AlternativeCost {
|
||||
Awaken,
|
||||
Bestow,
|
||||
Blitz,
|
||||
Cycling, // ActivatedAbility
|
||||
Dash,
|
||||
Disturb,
|
||||
|
||||
@@ -1424,6 +1424,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
return isAlternativeCost(AlternativeCost.Bestow);
|
||||
}
|
||||
|
||||
public final boolean isBlitz() {
|
||||
return isAlternativeCost(AlternativeCost.Blitz);
|
||||
}
|
||||
|
||||
public final boolean isDash() {
|
||||
return isAlternativeCost(AlternativeCost.Dash);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Name:Jaxis, the Troublemaker
|
||||
ManaCost:3 R
|
||||
Types:Legendary Creature Human Warrior
|
||||
PT:2/3
|
||||
A:AB$ CopyPermanent | Cost$ R T Discard<1/Card> | ValidTgts$ Creature.Other+YouCtrl | TgtPrompt$ Select another target creature you control | AddKeywords$ Haste | AddTriggers$ Dies | AddSVars$ TrigDraw | AtEOT$ Sacrifice | SorcerySpeed$ True | SpellDescription$ Create a token that's a copy of another target creature you control. It gains haste and "When this creature dies, draw a card." Sacrifice it at the beginning of the next end step. Activate only as a sorcery.
|
||||
SVar:Dies:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When this creature dies, draw a card.
|
||||
SVar:TrigDraw:DB$ Draw | NumCards$ 1
|
||||
K:Blitz:1 R
|
||||
Oracle:{R}, {T}, Discard a card: Create a token that's a copy of another target creature you control. It gains haste and "When this creature dies, draw a card." Sacrifice it at the beginning of the next end step. Activate only as a sorcery.\nBlitz {1}{R} (If you cast this spell for its blitz cost, it gains haste and "When this creature dies, draw a card." Sacrifice it at the beginning of the next end step.)
|
||||
Reference in New Issue
Block a user