mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Merge remote-tracking branch 'core/master' into AdventureModePort
This commit is contained in:
@@ -98,7 +98,7 @@ public abstract class SpellAbilityEffect {
|
||||
sb.append(" (Targeting: ").append(sa.getTargets()).append(")");
|
||||
}
|
||||
} else if (!"None".equalsIgnoreCase(stackDesc)) { // by typing "none" they want to suppress output
|
||||
makeSpellDescription(sa, sb, stackDesc);
|
||||
tokenizeString(sa, sb, stackDesc);
|
||||
}
|
||||
} else {
|
||||
final String condDesc = sa.getParam("ConditionDescription");
|
||||
@@ -155,7 +155,7 @@ public abstract class SpellAbilityEffect {
|
||||
* {@link Player}, {@link SpellAbility}, and {@link Card}
|
||||
* objects.
|
||||
*/
|
||||
private static void makeSpellDescription(final SpellAbility sa, final StringBuilder sb, final String stackDesc) {
|
||||
public static void tokenizeString(final SpellAbility sa, final StringBuilder sb, final String stackDesc) {
|
||||
final StringTokenizer st = new StringTokenizer(stackDesc, "{}", true);
|
||||
boolean isPlainText = true;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.*;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -16,11 +17,6 @@ import com.google.common.collect.Maps;
|
||||
import forge.GameCommand;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardType;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameActionUtil;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameEntityCounterTable;
|
||||
import forge.game.GameLogEntryType;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
@@ -81,12 +77,6 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final Card host = sa.getHostCard();
|
||||
|
||||
if (!(sa instanceof AbilitySub)) {
|
||||
sb.append(" -");
|
||||
}
|
||||
|
||||
sb.append(" ");
|
||||
|
||||
// Player whose cards will change zones
|
||||
List<Player> fetchers = null;
|
||||
if (sa.hasParam("DefinedPlayer")) {
|
||||
@@ -131,9 +121,14 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
String type = "card";
|
||||
if (sa.hasParam("ChangeTypeDesc")) {
|
||||
type = sa.getParam("ChangeTypeDesc");
|
||||
if (type.contains("{")) {
|
||||
final StringBuilder typesb = new StringBuilder();
|
||||
SpellAbilityEffect.tokenizeString(sa, typesb, type);
|
||||
type = typesb.toString();
|
||||
}
|
||||
else if (sa.hasParam("ChangeType")) {
|
||||
type = sa.getParam("ChangeType");
|
||||
} else if (sa.hasParam("ChangeType")) {
|
||||
final String ct = sa.getParam("ChangeType");
|
||||
type = CardType.CoreType.isValidEnum(ct) ? ct.toLowerCase() : ct;
|
||||
}
|
||||
|
||||
final int num = sa.hasParam("ChangeNum") ? AbilityUtils.calculateAmount(host,
|
||||
@@ -155,28 +150,26 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
sb.append(chooserNames);
|
||||
sb.append(" search").append(choosers.size() > 1 ? " " : "es ");
|
||||
sb.append(fetchPlayer).append(fetchPlayer.equals(chooserNames) ? "'s " : " ");
|
||||
sb.append("library for ").append(num).append(" ");
|
||||
sb.append(type).append(num > 1 ? "s" : "");
|
||||
sb.append("library for ").append(Lang.nounWithNumeralExceptOne(num, type + " card")).append(", ");
|
||||
if (!sa.hasParam("NoReveal")) {
|
||||
if (choosers.size() == 1) {
|
||||
sb.append(num > 1 ? ", reveals those cards," : ", reveals that card,");
|
||||
sb.append(num > 1 ? "reveals them, " : "reveals it, ");
|
||||
} else {
|
||||
sb.append(num > 1 ? ", reveal those cards," : ", reveal that card,");
|
||||
sb.append(num > 1 ? "reveal them, " : "reveal it, ");
|
||||
}
|
||||
}
|
||||
sb.append(" and ");
|
||||
|
||||
if (destination.equals("Exile")) {
|
||||
if (num == 1) {
|
||||
sb.append("exiles that card ");
|
||||
sb.append("exiles it");
|
||||
} else {
|
||||
sb.append("exiles those cards ");
|
||||
sb.append("exiles them");
|
||||
}
|
||||
} else {
|
||||
if (num == 1) {
|
||||
sb.append("puts that card ");
|
||||
sb.append("puts it ");
|
||||
} else {
|
||||
sb.append("puts those cards ");
|
||||
sb.append("puts them ");
|
||||
}
|
||||
|
||||
if (destination.equals("Battlefield")) {
|
||||
@@ -187,27 +180,23 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
if (sa.hasParam("GainControl")) {
|
||||
sb.append(" under ").append(chooserNames).append("'s control");
|
||||
}
|
||||
|
||||
sb.append(".");
|
||||
|
||||
}
|
||||
if (destination.equals("Hand")) {
|
||||
if (num == 1) {
|
||||
sb.append("into its owner's hand.");
|
||||
sb.append("into its owner's hand");
|
||||
} else {
|
||||
sb.append("into their owner's hand.");
|
||||
sb.append("into their owner's hand");
|
||||
}
|
||||
}
|
||||
if (destination.equals("Graveyard")) {
|
||||
if (num == 1) {
|
||||
sb.append("into its owner's graveyard.");
|
||||
sb.append("into its owner's graveyard");
|
||||
} else {
|
||||
sb.append("into their owner's graveyard.");
|
||||
}
|
||||
|
||||
sb.append("into their owner's graveyard");
|
||||
}
|
||||
}
|
||||
sb.append(" Then shuffle that library.");
|
||||
}
|
||||
sb.append(", then shuffles.");
|
||||
} else if (origin.equals("Sideboard")) {
|
||||
sb.append(chooserNames);
|
||||
//currently Reveal is always True in ChangeZone
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.game.ability.effects;
|
||||
import java.util.List;
|
||||
|
||||
import forge.util.Lang;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import forge.game.Game;
|
||||
@@ -37,12 +38,13 @@ public class TokenEffect extends TokenEffectBase {
|
||||
protected String getStackDescription(SpellAbility sa) {
|
||||
if (sa.hasParam("SpellDescription")) {
|
||||
String desc = sa.getParam("SpellDescription");
|
||||
if (desc.startsWith("Create")) {
|
||||
if (StringUtils.containsIgnoreCase(desc,"Create")) {
|
||||
final Card host = sa.getHostCard();
|
||||
final List<Player> creators = AbilityUtils.getDefinedPlayers(host, sa.getParamOrDefault("TokenOwner",
|
||||
"You"), sa);
|
||||
String start = Lang.joinHomogenous(creators) + (creators.size() == 1 ? " creates" : " create");
|
||||
desc = desc.replace("Create",start);
|
||||
String create = desc.contains("Create") ? "Create" : "create";
|
||||
desc = desc.replace(create, start);
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
12
forge-gui/res/cardsfolder/upcoming/anchor_to_reality.txt
Normal file
12
forge-gui/res/cardsfolder/upcoming/anchor_to_reality.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
Name:Anchor to Reality
|
||||
ManaCost:2 U U
|
||||
Types:Sorcery
|
||||
A:SP$ ChangeZone | Cost$ 2 U U Sac<1/Artifact;Creature/artifact or creature> | Origin$ Library | Destination$ Battlefield | ChangeType$ Equipment,Vehicle | ChangeTypeDesc$ Equipment or Vehicle card | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ DBScry | SpellDescription$ Search your library for an Equipment or Vehicle card, put that card onto the battlefield, then shuffle.
|
||||
SVar:DBScry:DB$ Scry | ConditionDefined$ Remembered | ConditionPresent$ Card | ScryNum$ X | SubAbility$ DBCleanup | SpellDescription$ If it has mana value less than the sacrificed permanent's mana value, scry 2.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:X:Count$Compare Y LTZ.2.0
|
||||
SVar:Y:Remembered$CardManaCost
|
||||
SVar:Z:Sacrificed$CardManaCost
|
||||
DeckNeeds:Type$Artifact|Creature|Equipment|Vehicle
|
||||
AI:RemoveDeck:Random
|
||||
Oracle:As an additional cost to cast this spell, sacrifice an artifact or creature.\nSearch your library for an Equipment or Vehicle card, put that card onto the battlefield, then shuffle. If it has mana value less than the sacrificed permanent's mana value, scry 2.
|
||||
8
forge-gui/res/cardsfolder/upcoming/blade_of_the_oni.txt
Normal file
8
forge-gui/res/cardsfolder/upcoming/blade_of_the_oni.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name:Blade of the Oni
|
||||
ManaCost:1 B
|
||||
Types:Artifact Creature Equipment Demon
|
||||
PT:3/1
|
||||
K:Menace
|
||||
K:Reconfigure:2 B B
|
||||
S:Mode$ Continuous | Affected$ Creature.EquippedBy | SetPower$ 5 | SetToughness$ 5 | AddKeyword$ Menace | AddType$ Demon | AddColor$ Black | Description$ Equipped creature has base power and toughness 5/5, has menace, and is a black Demon in addition to its other colors and types.
|
||||
Oracle:Menace\nEquipped creature has base power and toughness 5/5, has menace, and is a black Demon in addition to its other colors and types.\nReconfigure {2}{B}{B} ({2}{B}{B}: Attach to target creature you control; or unattach from a creature. Reconfigure only as a sorcery. While attached, this isn't a creature.)
|
||||
6
forge-gui/res/cardsfolder/upcoming/fang_of_shigeki.txt
Normal file
6
forge-gui/res/cardsfolder/upcoming/fang_of_shigeki.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Name:Fang of Shigeki
|
||||
ManaCost:G
|
||||
Types:Enchantment Creature Snake Ninja
|
||||
PT:1/1
|
||||
K:Deathtouch
|
||||
Oracle:Deathtouch
|
||||
@@ -0,0 +1,28 @@
|
||||
Name:Inventive Iteration
|
||||
ManaCost:3 U
|
||||
Types:Enchantment Saga
|
||||
K:Saga:3:DBReturn1,DBReturn2,DBTransform
|
||||
SVar:DBReturn1:DB$ ChangeZone | ValidTgts$ Creature,Planeswalker | TargetMin$ 0 | TargetMax$ 1 | Origin$ Battlefield | Destination$ Hand | TgtPrompt$ Select target creature or planeswalker | SpellDescription$ Return up to one target creature or planeswalker to its owner's hand.
|
||||
SVar:DBReturn2:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ChangeType$ Artifact | ChangeNum$ 1 Mandatory$ True | RememberChanged$ True | SubAbility$ DBDraw | SpellDescription$ Return an artifact card from your graveyard to your hand. If you can't, draw a card.
|
||||
SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1
|
||||
SVar:DBTransform:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBReturn | SpellDescription$ Exile this Saga, then return it to the battlefield transformed under your control.
|
||||
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | Transformed$ True | GainControl$ True | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
AlternateMode:DoubleFaced
|
||||
DeckHints:Type$Creature|Planeswalker|Artifact
|
||||
DeckHas:Ability$Graveyard
|
||||
Oracle:(As this Saga enters and after your draw step, add a lore counter.)\nI — Return up to one target creature or planeswalker to its owner's hand.\nII — Return an artifact card from your graveyard to your hand. If you can't, draw a card.\nIII — Exile this Saga, then return it to the battlefield transformed under your control.
|
||||
|
||||
ALTERNATE
|
||||
|
||||
Name:Living Breakthrough
|
||||
ManaCost:no cost
|
||||
Colors:blue
|
||||
Types:Enchantment Creature Moonfolk
|
||||
PT:3/3
|
||||
K:Flying
|
||||
T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ Whenever you cast a spell, your opponents can't cast spells with the same mana value as that spell until your next turn.
|
||||
SVar:TrigEffect:DB$ Effect | StaticAbilities$ OppCantCast | RememberObjects$ TriggeredCard | Duration$ UntilYourNextTurn
|
||||
SVar:OppCantCast:Mode$ CantBeCast | ValidCard$ Card.cmcEQX | Caster$ Opponent | Description$ Your opponents can't cast spells with the same mana value as that spell until your next turn.
|
||||
SVar:X:Remembered$CardManaCost
|
||||
Oracle:Flying\nWhenever you cast a spell, your opponents can't cast spells with the same mana value as that spell until your next turn.
|
||||
6
forge-gui/res/cardsfolder/upcoming/invoke_the_winds.txt
Normal file
6
forge-gui/res/cardsfolder/upcoming/invoke_the_winds.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
Name:Invoke the Winds
|
||||
ManaCost:1 U U U U
|
||||
Types:Sorcery
|
||||
A:SP$ GainControl | ValidTgts$ Artifact,Creature | TgtPrompt$ Select target artifact or creature | SubAbility$ DBUntap | SpellDescription$ Gain control of target artifact or creature.
|
||||
SVar:DBUntap:DB$ Untap | Defined$ Targeted | SpellDescription$ Untap it.
|
||||
Oracle:Gain control of target artifact or creature. Untap it.
|
||||
@@ -0,0 +1,12 @@
|
||||
Name:March of Burgeoning Life
|
||||
ManaCost:X G
|
||||
Types:Instant
|
||||
A:SP$ Pump | AnnounceTitle$ how many green cards to exile | Announce$ Exiled | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature.cmcLTX | TgtPrompt$ Choose target creature with mana value less than X | SubAbility$ DBSearch | StackDescription$ None | SpellDescription$ Choose target creature with mana value less than X. Search your library for a creature card with the same name as that creature, put it onto the battlefield tapped, then shuffle.
|
||||
SVar:DBSearch:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Targeted.Creature+sameName | ChangeTypeDesc$ creature card with the same name as {c:Targeted} | ChangeNum$ 1 | Mandatory$ True | Tapped$ True
|
||||
S:Mode$ RaiseCost | ValidCard$ Card.Self | Type$ Spell | Cost$ ExileFromHand<Y/Card.Green/green cards> | EffectZone$ All | Description$ As an additional cost to cast this spell, you may exile any number of green cards from your hand. This spell costs {2} less to cast for each card exiled this way.
|
||||
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Z | EffectZone$ All | Relative$ True | Secondary$ True | Description$ This spell costs {2} less to cast for each card exiled this way.
|
||||
SVar:X:Count$xPaid
|
||||
SVar:Y:SVar$Exiled
|
||||
SVar:Z:SVar$Y/Times.2
|
||||
SVar:Exiled:Number$0
|
||||
Oracle:As an additional cost to cast this spell, you may exile any number of green cards from your hand. This spell costs {2} less to cast for each card exiled this way.\nChoose target creature with mana value less than X. Search your library for a creature card with the same name as that creature, put it onto the battlefield tapped, then shuffle.
|
||||
10
forge-gui/res/cardsfolder/upcoming/prosperous_thief.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/prosperous_thief.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Name:Prosperous Thief
|
||||
ManaCost:2 U
|
||||
Types:Creature Human Ninja
|
||||
PT:3/2
|
||||
K:Ninjutsu:1 U
|
||||
T:Mode$ DamageDoneOnce | ValidSource$ Creature.Ninja+YouCtrl,Creature.Rogue+YouCtrl | TriggerZones$ Battlefield | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigToken | TriggerDescription$ Whenever one or more Ninja or Rogue creatures you control deal combat damage to a player, create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")
|
||||
SVar:TrigToken:DB$ Token | TokenScript$ c_a_treasure_sac
|
||||
DeckHints:Type$Ninja|Rogue
|
||||
DeckHas:Ability$Token|Sacrifice & Type$Artifact|Treasure
|
||||
Oracle:Ninjutsu {1}{U} ({1}{U}, Return an unblocked attacker you control to hand: Put this card onto the battlefield from your hand tapped and attacking.)\nWhenever one or more Ninja or Rogue creatures you control deal combat damage to a player, create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")
|
||||
@@ -3,10 +3,9 @@ ManaCost:2
|
||||
Types:Artifact Vehicle
|
||||
PT:4/4
|
||||
K:etbCounter:CHARGE:3
|
||||
A:AB$ Draw | Cost$ 2 T SubCounter<1/CHARGE> | SubAbility$ DBTreasure | SpellDescription$ Draw a card.
|
||||
SVar:DBTreasure:DB$ Token | TokenScript$ c_a_treasure_sac | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_CHARGE | SubAbility$ DBPilot | SpellDescription$ Then if there are no charge counters on CARDNAME, create a Treasure token
|
||||
SVar:DBPilot:DB$ Token | TokenScript$ c_1_1_pilot_crewbuff | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_CHARGE | SpellDescription$ and a 1/1 colorless Pilot creature token with "This creature crews Vehicles as though its power were 2 greater."
|
||||
A:AB$ Draw | Cost$ 2 T SubCounter<1/CHARGE> | SubAbility$ DBToken | SpellDescription$ Draw a card.
|
||||
SVar:DBToken:DB$ Token | TokenScript$ c_a_treasure_sac,c_1_1_pilot_crewbuff | ConditionDefined$ Self | ConditionPresent$ Card.counters_EQ0_CHARGE | SubAbility$ DBPilot | SpellDescription$ Then if there are no charge counters on CARDNAME, create a Treasure token and a 1/1 colorless Pilot creature token with "This creature crews Vehicles as though its power were 2 greater."
|
||||
K:Crew:3
|
||||
DeckHas:Ability$Counters|Token|Sacrifice & Type$Pilot
|
||||
DeckHas:Ability$Counters|Token|Sacrifice & Type$Pilot|Treasure
|
||||
DeckHints:Type$Vehicle
|
||||
Oracle:Reckoner Bankbuster enters the battlefield with three charge counters on it.\n{2}, {T}, Remove a charge counter from Reckoner Bankbuster: Draw a card. Then if there are no charge counters on Reckoner Bankbuster, create a Treasure token and a 1/1 colorless Pilot creature token with "This creature crews Vehicles as though its power were 2 greater."\nCrew 3
|
||||
|
||||
Reference in New Issue
Block a user