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")) {
|
} else if (property.equals("hasTapCost")) {
|
||||||
Cost cost = sa.getPayCosts();
|
Cost cost = sa.getPayCosts();
|
||||||
return cost != null && cost.hasTapCost();
|
return cost != null && cost.hasTapCost();
|
||||||
|
} else if (property.equals("Blitz")) {
|
||||||
|
return sa.isBlitz();
|
||||||
} else if (property.equals("Buyback")) {
|
} else if (property.equals("Buyback")) {
|
||||||
return sa.isBuyBackAbility();
|
return sa.isBuyBackAbility();
|
||||||
} else if (property.equals("Cycling")) {
|
} 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
|
// Clean up the temporary AtEOT SVar
|
||||||
String endofTurn = c.getSVar("EndOfTurnLeavePlay");
|
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");
|
c.removeSVar("EndOfTurnLeavePlay");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,18 +44,40 @@ public class CopyPermanentEffect extends TokenEffectBase {
|
|||||||
}
|
}
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
final Player activator = sa.getActivatingPlayer();
|
||||||
final List<Card> tgtCards = getTargetCards(sa);
|
final List<Card> tgtCards = getTargetCards(sa);
|
||||||
boolean justOne = tgtCards.size() == 1;
|
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));
|
sb.append(Lang.joinHomogenous(tgtCards));
|
||||||
if (sa.hasParam("AddKeywords")) {
|
|
||||||
|
if (addKWs) {
|
||||||
final List<String> keywords = Lists.newArrayList();
|
final List<String> keywords = Lists.newArrayList();
|
||||||
keywords.addAll(Arrays.asList(sa.getParam("AddKeywords").split(" & ")));
|
keywords.addAll(Arrays.asList(sa.getParam("AddKeywords").split(" & ")));
|
||||||
sb.append(", except ").append(justOne ? "it has " : "they have ");
|
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());
|
sb.append(Lang.joinHomogenous(keywords).toLowerCase());
|
||||||
}
|
}
|
||||||
sb.append(".");
|
|
||||||
|
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")) {
|
if (sa.hasParam("AtEOT")) {
|
||||||
String atEOT = sa.getParam("AtEOT");
|
String atEOT = sa.getParam("AtEOT");
|
||||||
String verb = "Sacrifice ";
|
String verb = "Sacrifice ";
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public class PermanentEffect extends SpellAbilityEffect {
|
|||||||
c.setSVar("EndOfTurnLeavePlay", "Dash");
|
c.setSVar("EndOfTurnLeavePlay", "Dash");
|
||||||
registerDelayedTrigger(sa, "Hand", Lists.newArrayList(c));
|
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();
|
ZoneType newZone = c.getZone().getZoneType();
|
||||||
if (newZone != previousZone) {
|
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("Transfigure") || keyword.startsWith("Aura swap")
|
||||||
|| keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling")
|
|| keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling")
|
||||||
|| keyword.startsWith("Encore") || keyword.startsWith("Mutate") || keyword.startsWith("Dungeon")
|
|| 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
|
// keyword parsing takes care of adding a proper description
|
||||||
} else if (keyword.equals("Unblockable")) {
|
} else if (keyword.equals("Unblockable")) {
|
||||||
sbLong.append(getName()).append(" can't be blocked.\r\n");
|
sbLong.append(getName()).append(" can't be blocked.\r\n");
|
||||||
|
|||||||
@@ -2706,6 +2706,26 @@ public class CardFactoryUtil {
|
|||||||
sa.setAlternativeCost(AlternativeCost.Bestow);
|
sa.setAlternativeCost(AlternativeCost.Bestow);
|
||||||
sa.setIntrinsic(intrinsic);
|
sa.setIntrinsic(intrinsic);
|
||||||
inst.addSpellAbility(sa);
|
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")) {
|
} else if (keyword.startsWith("Class")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final int level = Integer.valueOf(k[1]);
|
final int level = Integer.valueOf(k[1]);
|
||||||
@@ -3455,6 +3475,18 @@ public class CardFactoryUtil {
|
|||||||
StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic);
|
StaticAbility st = StaticAbility.create(effect, state.getCard(), state, intrinsic);
|
||||||
|
|
||||||
st.setSVar("AffinityX", "Count$Valid " + t + ".YouCtrl");
|
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);
|
inst.addStaticAbility(st);
|
||||||
} else if (keyword.equals("Changeling")) {
|
} else if (keyword.equals("Changeling")) {
|
||||||
String effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" +
|
String effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" +
|
||||||
|
|||||||
@@ -1684,6 +1684,11 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return card.getCastSA().isSurged();
|
return card.getCastSA().isSurged();
|
||||||
|
} else if (property.equals("blitzed")) {
|
||||||
|
if (card.getCastSA() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return card.getCastSA().isBlitz();
|
||||||
} else if (property.equals("dashed")) {
|
} else if (property.equals("dashed")) {
|
||||||
if (card.getCastSA() == null) {
|
if (card.getCastSA() == null) {
|
||||||
return false;
|
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."),
|
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."),
|
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."),
|
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."),
|
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."),
|
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."),
|
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 {
|
public enum AlternativeCost {
|
||||||
Awaken,
|
Awaken,
|
||||||
Bestow,
|
Bestow,
|
||||||
|
Blitz,
|
||||||
Cycling, // ActivatedAbility
|
Cycling, // ActivatedAbility
|
||||||
Dash,
|
Dash,
|
||||||
Disturb,
|
Disturb,
|
||||||
|
|||||||
@@ -1424,6 +1424,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
return isAlternativeCost(AlternativeCost.Bestow);
|
return isAlternativeCost(AlternativeCost.Bestow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean isBlitz() {
|
||||||
|
return isAlternativeCost(AlternativeCost.Blitz);
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean isDash() {
|
public final boolean isDash() {
|
||||||
return isAlternativeCost(AlternativeCost.Dash);
|
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