mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Merge branch 'master' into 'master'
Add more cards See merge request core-developers/forge!992
This commit is contained in:
@@ -428,6 +428,7 @@ public class GameAction {
|
|||||||
if (!c.isToken() && !toBattlefield) {
|
if (!c.isToken() && !toBattlefield) {
|
||||||
copied.clearDevoured();
|
copied.clearDevoured();
|
||||||
copied.clearDelved();
|
copied.clearDelved();
|
||||||
|
copied.clearConvoked();
|
||||||
}
|
}
|
||||||
|
|
||||||
// rule 504.6: reveal a face-down card leaving the stack
|
// rule 504.6: reveal a face-down card leaving the stack
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import forge.game.GameEntity;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardFactory;
|
import forge.game.card.CardFactory;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -123,7 +124,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
} else {// Precursor Golem, Ink-Treader Nephilim
|
} else {// Precursor Golem, Ink-Treader Nephilim
|
||||||
final String type = sa.getParam("CopyForEachCanTarget");
|
final String type = sa.getParam("CopyForEachCanTarget");
|
||||||
List<Card> valid = Lists.newArrayList();
|
CardCollection valid = new CardCollection();
|
||||||
List<Player> players = Lists.newArrayList();
|
List<Player> players = Lists.newArrayList();
|
||||||
Player originalTargetPlayer = Iterables.getFirst(getTargetPlayers(chosenSA), null);
|
Player originalTargetPlayer = Iterables.getFirst(getTargetPlayers(chosenSA), null);
|
||||||
for (final GameEntity o : candidates) {
|
for (final GameEntity o : candidates) {
|
||||||
@@ -142,10 +143,17 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
|
|||||||
Card originalTarget = Iterables.getFirst(getTargetCards(chosenSA), null);
|
Card originalTarget = Iterables.getFirst(getTargetCards(chosenSA), null);
|
||||||
valid.remove(originalTarget);
|
valid.remove(originalTarget);
|
||||||
mayChooseNewTargets = false;
|
mayChooseNewTargets = false;
|
||||||
for (final Card c : valid) {
|
if (sa.hasParam("ChooseOnlyOne")) {
|
||||||
|
Card choice = controller.getController().chooseSingleEntityForEffect(valid, sa, "Choose one");
|
||||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||||
resetFirstTargetOnCopy(copy, c, targetedSA);
|
resetFirstTargetOnCopy(copy, choice, targetedSA);
|
||||||
copies.add(copy);
|
copies.add(copy);
|
||||||
|
} else {
|
||||||
|
for (final Card c : valid) {
|
||||||
|
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||||
|
resetFirstTargetOnCopy(copy, c, targetedSA);
|
||||||
|
copies.add(copy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (final Player p : players) {
|
for (final Player p : players) {
|
||||||
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
SpellAbility copy = CardFactory.copySpellAbilityAndPossiblyHost(card, chosenSA.getHostCard(), chosenSA, true);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
|
private final KeywordCollection hiddenExtrinsicKeyword = new KeywordCollection();
|
||||||
|
|
||||||
// cards attached or otherwise linked to this card
|
// cards attached or otherwise linked to this card
|
||||||
private CardCollection equippedBy, fortifiedBy, hauntedBy, devouredCards, delvedCards, imprintedCards, encodedCards;
|
private CardCollection equippedBy, fortifiedBy, hauntedBy, devouredCards, delvedCards, convokedCards, imprintedCards, encodedCards;
|
||||||
private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn;
|
private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn;
|
||||||
|
|
||||||
// if this card is attached or linked to something, what card is it currently attached to
|
// if this card is attached or linked to something, what card is it currently attached to
|
||||||
@@ -725,6 +725,20 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
delvedCards = null;
|
delvedCards = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final CardCollectionView getConvoked() {
|
||||||
|
return CardCollection.getView(convokedCards);
|
||||||
|
}
|
||||||
|
public final void addConvoked(final Card c) {
|
||||||
|
if (convokedCards == null) {
|
||||||
|
convokedCards = new CardCollection();
|
||||||
|
}
|
||||||
|
convokedCards.add(c);
|
||||||
|
}
|
||||||
|
public final void clearConvoked() {
|
||||||
|
convokedCards = null;
|
||||||
|
}
|
||||||
|
|
||||||
public MapOfLists<GameEntity, Object> getRememberMap() {
|
public MapOfLists<GameEntity, Object> getRememberMap() {
|
||||||
return rememberMap;
|
return rememberMap;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1378,6 +1378,10 @@ public class CardProperty {
|
|||||||
if (!source.getDelved().contains(card)) {
|
if (!source.getDelved().contains(card)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (property.startsWith("convoked")) {
|
||||||
|
if (!source.getConvoked().contains(card)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (property.startsWith("unequalPT")) {
|
} else if (property.startsWith("unequalPT")) {
|
||||||
if (card.getNetPower() == card.getNetToughness()) {
|
if (card.getNetPower() == card.getNetToughness()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ public class CostAdjustment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sa.getHostCard().hasKeyword(Keyword.CONVOKE)) {
|
if (sa.getHostCard().hasKeyword(Keyword.CONVOKE)) {
|
||||||
|
sa.getHostCard().clearConvoked();
|
||||||
adjustCostByConvokeOrImprovise(cost, sa, false, test);
|
adjustCostByConvokeOrImprovise(cost, sa, false, test);
|
||||||
}
|
}
|
||||||
if (sa.getHostCard().hasKeyword(Keyword.IMPROVISE)) {
|
if (sa.getHostCard().hasKeyword(Keyword.IMPROVISE)) {
|
||||||
@@ -270,6 +271,9 @@ public class CostAdjustment {
|
|||||||
cost.decreaseShard(conv.getValue(), 1);
|
cost.decreaseShard(conv.getValue(), 1);
|
||||||
if (!test) {
|
if (!test) {
|
||||||
conv.getKey().tap();
|
conv.getKey().tap();
|
||||||
|
if (!improvise) {
|
||||||
|
sa.getHostCard().addConvoked(conv.getKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ import java.util.Set;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
@@ -158,6 +160,31 @@ public class TriggerSpellAbilityCast extends Trigger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasParam("CanTargetOtherCondition")) {
|
||||||
|
final CardCollection candidates = new CardCollection();
|
||||||
|
SpellAbility targetedSA = spellAbility;
|
||||||
|
while (targetedSA != null) {
|
||||||
|
if (targetedSA.usesTargeting() && targetedSA.getTargets().getNumTargeted() != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
targetedSA = targetedSA.getSubAbility();
|
||||||
|
}
|
||||||
|
if (targetedSA == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final List<GameEntity> candidateTargets = targetedSA.getTargetRestrictions().getAllCandidates(targetedSA, true);
|
||||||
|
for (GameEntity card : candidateTargets) {
|
||||||
|
if (card instanceof Card) {
|
||||||
|
candidates.add((Card) card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
candidates.removeAll(targetedSA.getTargets().getTargetCards());
|
||||||
|
String valid = this.mapParams.get("CanTargetOtherCondition");
|
||||||
|
if (CardLists.getValidCards(candidates, valid, spellAbility.getActivatingPlayer(), spellAbility.getHostCard()).isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hasParam("NonTapCost")) {
|
if (hasParam("NonTapCost")) {
|
||||||
final Cost cost = (Cost) (runParams2.get("Cost"));
|
final Cost cost = (Cost) (runParams2.get("Cost"));
|
||||||
if (cost.hasTapCost()) {
|
if (cost.hasTapCost()) {
|
||||||
|
|||||||
7
forge-gui/res/cardsfolder/b/beamsplitter_mage.txt
Normal file
7
forge-gui/res/cardsfolder/b/beamsplitter_mage.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Beamsplitter Mage
|
||||||
|
ManaCost:U R
|
||||||
|
Types:Creature Vedalken Wizard
|
||||||
|
PT:2/2
|
||||||
|
T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | IsSingleTarget$ True | TargetsValid$ Card.Self | CanTargetOtherCondition$ Creature.YouCtrl | Execute$ TrigCopy | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast an instant or sorcery that targets only CARDNAME, if you control one or more other creatures that spell could target, choose one of those creatures. Copy that spell. The copy targets the chosen creature.
|
||||||
|
SVar:TrigCopy:DB$ CopySpellAbility | Defined$ TriggeredSpellAbility | Controller$ You | CopyForEachCanTarget$ Creature.YouCtrl | ChooseOnlyOne$ True
|
||||||
|
Oracle:Whenever you cast an instant or sorcery spell that targets only Beamsplitter Mage, if you control one or more other creatures that spell could target, choose one of those creatures. Copy that spell. The copy targets the chosen creature.
|
||||||
10
forge-gui/res/cardsfolder/l/lazav_the_multifarious.txt
Normal file
10
forge-gui/res/cardsfolder/l/lazav_the_multifarious.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Lazav, the Multifarious
|
||||||
|
ManaCost:U B
|
||||||
|
Types:Legendary Creature Shapeshifter
|
||||||
|
PT:1/3
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSurveil | TriggerDescription$ When CARDNAME enters the battlefield, scry 1. (To scry 1, look at the top card of your library. You may put that card into your graveyard.)
|
||||||
|
SVar:TrigSurveil:DB$ Surveil | Amount$ 1
|
||||||
|
A:AB$ Clone | Cost$ X | ValidTgts$ Creature.YouOwn | References$ X | TgtZone$ Graveyard | TgtPrompt$ Select target creature card in your graveyard | AddTypes$ Legendary | KeepName$ True | AddSVars$ X,LazavTrig | AddAbilities$ LazavTrig | SpellDescription$ CARDNAME becomes a copy of target creature card in your graveyard with converted mana cost X, except its name is CARDNAME, it's legendary in addition to it's other types, and it has this ability.
|
||||||
|
SVar:LazavTrig:AB$ Clone | Cost$ X | ValidTgts$ Creature.YouOwn | References$ X | TgtZone$ Graveyard | TgtPrompt$ Select target creature card in your graveyard | AddTypes$ Legendary | KeepName$ True | AddSVars$ X,LazavTrig | AddAbilities$ LazavTrig | SpellDescription$ CARDNAME becomes a copy of target creature card in your graveyard with converted mana cost X, except its name is CARDNAME, it's legendary in addition to it's other types, and it has this ability.
|
||||||
|
SVar:X:Targeted$CardManaCost
|
||||||
|
Oracle:When Lazav, the Multifarious enters the battlefield, surveil 1. (Look at the top card of your library. You may put that card into your graveyard.)\n{X}: Lazav, the Multifarious becomes a copy of target creature card in your graveyard with converted mana cost X, except its name is Lazav, the Multifarious, it's legendary in addition to its other types, and it has this ability.
|
||||||
8
forge-gui/res/cardsfolder/v/venerated_loxodon.txt
Normal file
8
forge-gui/res/cardsfolder/v/venerated_loxodon.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Venerated Loxodon
|
||||||
|
ManaCost:4 W
|
||||||
|
Types:Creature Elephant Cleric
|
||||||
|
PT:4/4
|
||||||
|
K:Convoke
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPutCounterAll | TriggerDescription$ When CARDNAME enters the battlefield, put a +1/+1 counter on each creature that convoked it.
|
||||||
|
SVar:TrigPutCounterAll:DB$ PutCounterAll | ValidCards$ Creature.convoked | CounterType$ P1P1 | CounterNum$ 1
|
||||||
|
Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of the creature's color.)\nWhen Venerated Loxodon enters the battlefield, put a +1/+1 counter on each creature that convoked it.
|
||||||
Reference in New Issue
Block a user