mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
MOM: Backup keyword and cards (#2799)
* Backup keyword setup * Backup cards * KeywordWithAmount spacing * mirror_shield_hoplite.txt and support * fix for KeywordWithAmount * doomskar_warrior.txt fearless_skald.txt * add PlayMain1 * typo fix * add logic to ComputerUtil.castPermanentInMain1 instead of using PlayMain1 on cardscripts
This commit is contained in:
@@ -1074,6 +1074,15 @@ public class ComputerUtil {
|
||||
}
|
||||
}
|
||||
|
||||
// cast Backup creatures in main 1 to pump attackers
|
||||
if (cardState.hasKeyword(Keyword.BACKUP)) {
|
||||
for (Card potentialAtkr: ai.getCreaturesInPlay()) {
|
||||
if (ComputerUtilCard.doesCreatureAttackAI(ai, potentialAtkr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try not to cast Raid creatures in main 1 if an attack is likely
|
||||
if ("Count$AttackersDeclared".equals(card.getSVar("RaidTest")) && !cardState.hasKeyword(Keyword.HASTE)) {
|
||||
for (Card potentialAtkr: ai.getCreaturesInPlay()) {
|
||||
|
||||
@@ -193,6 +193,8 @@ public class ForgeScript {
|
||||
} else if (property.equals("hasTapCost")) {
|
||||
Cost cost = sa.getPayCosts();
|
||||
return cost != null && cost.hasTapCost();
|
||||
} else if (property.equals("Backup")) {
|
||||
return sa.isBackup();
|
||||
} else if (property.equals("Blitz")) {
|
||||
return sa.isBlitz();
|
||||
} else if (property.equals("Buyback")) {
|
||||
|
||||
@@ -2303,10 +2303,18 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
|| keyword.startsWith("Specialize") || keyword.equals("Ravenous")
|
||||
|| keyword.equals("For Mirrodin")) {
|
||||
// keyword parsing takes care of adding a proper description
|
||||
} else if(keyword.startsWith("Read ahead")) {
|
||||
} else if (keyword.startsWith("Read ahead")) {
|
||||
sb.append(Localizer.getInstance().getMessage("lblReadAhead")).append(" (").append(Localizer.getInstance().getMessage("lblReadAheadDesc"));
|
||||
sb.append(" ").append(Localizer.getInstance().getMessage("lblSagaFooter")).append(" ").append(TextUtil.toRoman(getFinalChapterNr())).append(".");
|
||||
sb.append(")").append("\r\n\r\n");
|
||||
} else if (keyword.startsWith("Backup")) {
|
||||
final String[] k = keyword.split(":");
|
||||
sb.append(k[0]).append(" ").append(k[1]).append(" (");
|
||||
String remStr = inst.getReminderText();
|
||||
if (k[2].endsWith("s")) {
|
||||
remStr = remStr.replace("ability", "abilities");
|
||||
}
|
||||
sb.append(remStr).append(")");
|
||||
} else if (keyword.startsWith("MayEffectFromOpening")) {
|
||||
final String[] k = keyword.split(":");
|
||||
// need to get SpellDescription from Svar
|
||||
@@ -2325,7 +2333,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
sbLong.append("\r\n");
|
||||
}
|
||||
|
||||
if (keyword.equals("Flash")) {
|
||||
if (keyword.equals("Flash") || keyword.startsWith("Backup")) {
|
||||
sb.append("\r\n\r\n");
|
||||
i = 0;
|
||||
} else {
|
||||
|
||||
@@ -839,6 +839,31 @@ public class CardFactoryUtil {
|
||||
sa.setBlessing(true);
|
||||
}
|
||||
}
|
||||
} else if (keyword.startsWith("Backup")) {
|
||||
final String[] k = keyword.split(":");
|
||||
final String magnitude = k[1];
|
||||
final String backupVar = card.getSVar(k[2]);
|
||||
|
||||
String descStr = "Backup " + magnitude;
|
||||
|
||||
final String trigStr = "Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | " +
|
||||
"Secondary$ True | TriggerDescription$ " + descStr;
|
||||
|
||||
final String putCounter = "DB$ PutCounter | ValidTgts$ Creature | CounterNum$ " + magnitude
|
||||
+ " | CounterType$ P1P1 | Backup$ True";
|
||||
|
||||
final String addAbility = backupVar + " | ConditionDefined$ Targeted | " +
|
||||
"ConditionPresent$ Card.Other | Defined$ Targeted";
|
||||
|
||||
SpellAbility sa = AbilityFactory.getAbility(putCounter, card);
|
||||
AbilitySub backupSub = (AbilitySub) AbilityFactory.getAbility(addAbility, card);
|
||||
sa.setSubAbility(backupSub);
|
||||
|
||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
||||
sa.setIntrinsic(intrinsic);
|
||||
trigger.setOverridingAbility(sa);
|
||||
|
||||
inst.addTrigger(trigger);
|
||||
} else if (keyword.equals("Battle cry")) {
|
||||
final String trig = "Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Secondary$ True "
|
||||
+ " | TriggerDescription$ " + keyword + " (" + inst.getReminderText() + ")";
|
||||
@@ -1151,7 +1176,7 @@ public class CardFactoryUtil {
|
||||
} else if (keyword.equals("Extort")) {
|
||||
final String extortTrigger = "Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | "
|
||||
+ "TriggerZones$ Battlefield | Secondary$ True"
|
||||
+ " | TriggerDescription$ Extort ("+ inst.getReminderText() +")";
|
||||
+ " | TriggerDescription$ Extort (" + inst.getReminderText() + ")";
|
||||
|
||||
final String loseLifeStr = "AB$ LoseLife | Cost$ WB | Defined$ Player.Opponent | LifeAmount$ 1";
|
||||
final String gainLifeStr = "DB$ GainLife | Defined$ You | LifeAmount$ AFLifeLost";
|
||||
@@ -2687,7 +2712,7 @@ public class CardFactoryUtil {
|
||||
if (keyword.startsWith("Alternative Cost") && !host.isLand()) {
|
||||
final String[] kw = keyword.split(":");
|
||||
String costStr = kw[1];
|
||||
for (SpellAbility sa: host.getBasicSpells()) {
|
||||
for (SpellAbility sa : host.getBasicSpells()) {
|
||||
if (costStr.equals("ConvertedManaCost")) {
|
||||
costStr = Integer.toString(host.getCMC());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public enum Keyword {
|
||||
ASSIST("Assist", SimpleKeyword.class, true, "Another player can pay up to %s of this spell's cost."),
|
||||
AURA_SWAP("Aura swap", KeywordWithCost.class, false, "%s: You may exchange this Aura with an Aura card in your hand."),
|
||||
AWAKEN("Awaken", KeywordWithCostAndAmount.class, false, "If you cast this spell for %s, also put {%d:+1/+1 counter} on target land you control and it becomes a 0/0 Elemental creature with haste. It's still a land."),
|
||||
BACKUP("Backup", KeywordWithAmount.class, false, "When this creature enters the battlefield, put {%1$d:+1/+1 counter} on target creature. If that's another creature, it gains the following ability until end of turn."),
|
||||
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."),
|
||||
|
||||
@@ -17,8 +17,8 @@ public class KeywordWithAmount extends KeywordInstance<KeywordWithAmount> {
|
||||
if (details.contains(":")) {
|
||||
extra = details.split(":")[1];
|
||||
}
|
||||
} else {
|
||||
amount = Integer.parseInt(details);
|
||||
} else {
|
||||
amount = details.contains(":") ? Integer.parseInt(details.split(":")[0]) : Integer.parseInt(details);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -508,6 +508,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
return isAlternativeCost(AlternativeCost.Cycling);
|
||||
}
|
||||
|
||||
public boolean isBackup() {
|
||||
return this.hasParam("Backup");
|
||||
}
|
||||
|
||||
public boolean isBoast() {
|
||||
return this.hasParam("Boast");
|
||||
}
|
||||
|
||||
13
forge-gui/res/cardsfolder/upcoming/archpriest_of_shadows.txt
Normal file
13
forge-gui/res/cardsfolder/upcoming/archpriest_of_shadows.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Archpriest of Shadows
|
||||
ManaCost:3 B B
|
||||
Types:Creature Human Warlock
|
||||
PT:4/4
|
||||
K:Backup:1:BackupAbilities
|
||||
SVar:BackupAbilities:DB$ Animate | Keywords$ Deathtouch | Triggers$ DamageTrig
|
||||
SVar:DamageTrig:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player,Battle | Execute$ TrigReturn | CombatDamage$ True | TriggerDescription$ Whenever this creature deals combat damage to a player or battle, return target creature card from your graveyard to the battlefield.
|
||||
K:Deathtouch
|
||||
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player,Battle | Execute$ TrigReturn | CombatDamage$ True | TriggerDescription$ Whenever this creature deals combat damage to a player or battle, return target creature card from your graveyard to the battlefield.
|
||||
SVar:TrigReturn:DB$ ChangeZone | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature from your graveyard | Origin$ Graveyard | Destination$ Battlefield
|
||||
DeckHas:Ability$Counters|Graveyard
|
||||
DeckHints:Ability$Discard|Sacrifice
|
||||
Oracle:Backup 1 (When this creature enters the battlefield, put a +1/+1 counter on target creature. If that's another creature, it gains the following abilities until end of turn.)\nDeathtouch\nWhenever this creature deals combat damage to a player or battle, return target creature card from your graveyard to the battlefield.
|
||||
11
forge-gui/res/cardsfolder/upcoming/boon_bringer_valkyrie.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/boon_bringer_valkyrie.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Name:Boon-Bringer Valkyrie
|
||||
ManaCost:3 W W
|
||||
Types:Creature Angel Warrior
|
||||
PT:4/4
|
||||
K:Backup:1:BackupAbilities
|
||||
SVar:BackupAbilities:DB$ Pump | KW$ Flying & First Strike & Lifelink
|
||||
K:Flying
|
||||
K:First Strike
|
||||
K:Lifelink
|
||||
DeckHas:Ability$Counters|LifeGain
|
||||
Oracle:Backup 1 (When this creature enters the battlefield, put a +1/+1 counter on target creature. If that’s another creature, it gains the following abilities until end of turn.)\nFlying, first strike, lifelink
|
||||
10
forge-gui/res/cardsfolder/upcoming/cragsmasher_yeti.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/cragsmasher_yeti.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Name:Cragsmasher Yeti
|
||||
ManaCost:4 R R
|
||||
Types:Creature Yeti
|
||||
PT:4/2
|
||||
K:TypeCycling:Mountain:2
|
||||
K:Backup:2:BackupAbility
|
||||
SVar:BackupAbility:DB$ Pump | KW$ Trample
|
||||
K:Trample
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Mountaincycling {2} ({2}, Discard this card: Search your library for a Mountain card, reveal it, put it into your hand, then shuffle.)\nBackup 2 (When this creature enters the battlefield, put two +1/+1 counters on target creature. If that's another creature, it gains the following ability until end of turn.)\nTrample
|
||||
13
forge-gui/res/cardsfolder/upcoming/doomskar_warrior.txt
Normal file
13
forge-gui/res/cardsfolder/upcoming/doomskar_warrior.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Doomskar Warrior
|
||||
ManaCost:2 G G
|
||||
Types:Creature Human Warrior
|
||||
PT:4/3
|
||||
K:Backup:1:BackupAbilities
|
||||
SVar:BackupAbilities:DB$ Animate | Keywords$ Trample | Triggers$ DamageTrig
|
||||
SVar:DamageTrig:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player,Battle | Execute$ TrigDig | CombatDamage$ True | TriggerDescription$ Whenever this creature deals combat damage to a player or battle, look at that many cards from the top of your library. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
||||
SVar:TrigDig:DB$ Dig | DigNum$ X | ChangeNum$ 1 | ChangeValid$ Creature,Land | Optional$ True | DestinationZone$ Hand | RestRandomOrder$ True
|
||||
K:Trample
|
||||
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player,Planeswalker | Execute$ TrigDig | CombatDamage$ True | TriggerDescription$ Whenever this creature deals combat damage to a player or battle, look at that many cards from the top of your library. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
||||
SVar:X:TriggerCount$DamageAmount
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Backup 1\nTrample\nWhenever this creature deals combat damage to a player or battle, look at that many cards from the top of your library. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
||||
9
forge-gui/res/cardsfolder/upcoming/fearless_skald.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/fearless_skald.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Name:Fearless Skald
|
||||
ManaCost:4 R
|
||||
Types:Creature Dwarf Berserker
|
||||
PT:3/2
|
||||
K:Backup:1:BackupAbility
|
||||
SVar:BackupAbility:DB$ Pump | KW$ Double Strike
|
||||
K:Double Strike
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Backup 1 (When this creature enters the battlefield, put a + 1/+ 1 counter on target creature. If that's another creature, it gains the following ability until end of turn.)\nDouble strike
|
||||
@@ -0,0 +1,9 @@
|
||||
Name:Mirror-Shield Hoplite
|
||||
ManaCost:R W
|
||||
Types:Creature Human Soldier
|
||||
PT:2/2
|
||||
K:Vigilance
|
||||
T:Mode$ BecomesTarget | ValidTarget$ Creature.inZoneBattlefield+YouCtrl | ValidSource$ Ability.Backup | TriggerZones$ Battlefield | Execute$ TrigCopy | ActivationLimit$ 1 | TriggerDescription$ Whenever a creature you control becomes the target of a backup ability, copy that ability. You may choose new targets for the copy. This ability triggers only once each turn.
|
||||
SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredStackInstance | MayChooseTarget$ True
|
||||
DeckNeeds:Keyword$Backup
|
||||
Oracle:Vigilance\nWhenever a creature you control becomes the target of a backup ability, copy that ability. You may choose new targets for the copy. This ability triggers only once each turn.
|
||||
@@ -0,0 +1,10 @@
|
||||
Name:Streetwise Negotiator
|
||||
ManaCost:1 G
|
||||
Types:Creature Cat Citizen
|
||||
PT:0/2
|
||||
K:Backup:1:BackupAbility
|
||||
SVar:BackupAbility:DB$ Animate | staticAbilities$ CDT
|
||||
SVar:CDT:Mode$ CombatDamageToughness | ValidCard$ Card.Self | Description$ This creature assigns combat damage equal to its toughness rather than its power.
|
||||
S:Mode$ CombatDamageToughness | ValidCard$ Card.Self | Description$ This creature assigns combat damage equal to its toughness rather than its power.
|
||||
DeckHas:Ability$Counters
|
||||
Oracle:Backup 1 (When this creature enters the battlefield, put a +1/+1 counter on target creature. If that's another creature, it gains the following ability until end of turn.)\nThis creature assigns combat damage equal to its toughness rather than its power.
|
||||
11
forge-gui/res/cardsfolder/upcoming/voldaren_thrilseeker.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/voldaren_thrilseeker.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Name:Voldaren Thrillseeker
|
||||
ManaCost:2 R
|
||||
Types:Creature Vampire Warrior
|
||||
PT:1/1
|
||||
K:Backup:2:BackupAbility
|
||||
SVar:BackupAbility:DB$ Animate | Abilities$ ABDealDamage
|
||||
SVar:ABDealDamage:AB$ DealDamage | Cost$ 1 Sac<1/CARDNAME/this creature> | ValidTgts$ Player,Creature,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | SpellDescription$ It deals damage equal to its power to any target.
|
||||
A:AB$ DealDamage | Cost$ 1 Sac<1/CARDNAME/this creature> | ValidTgts$ Player,Creature,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | SpellDescription$ It deals damage equal to its power to any target.
|
||||
SVar:X:Sacrificed$CardPower
|
||||
DeckHas:Ability$Counters|Sacrifice
|
||||
Oracle:Backup 2 (When this creature enters the battlefield, put two +1/+1 counters on target creature. If that's another creature, it gains the following ability until end of turn.)\n{1}, Sacrifice this creature: It deals damage equal to its power to any target.
|
||||
Reference in New Issue
Block a user