mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
- Added Cairn Wanderer, Concerted Effort, and Death-Mask Duplicant
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1420,6 +1420,7 @@ res/cardsfolder/c/cadaverous_bloom.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/c/cadaverous_knight.txt svneol=native#text/plain
|
res/cardsfolder/c/cadaverous_knight.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/cage_of_hands.txt svneol=native#text/plain
|
res/cardsfolder/c/cage_of_hands.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/cagemail.txt svneol=native#text/plain
|
res/cardsfolder/c/cagemail.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/c/cairn_wanderer.txt -text
|
||||||
res/cardsfolder/c/calciderm.txt svneol=native#text/plain
|
res/cardsfolder/c/calciderm.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/calciform_pools.txt svneol=native#text/plain
|
res/cardsfolder/c/calciform_pools.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/calcite_snapper.txt svneol=native#text/plain
|
res/cardsfolder/c/calcite_snapper.txt svneol=native#text/plain
|
||||||
@@ -1925,6 +1926,7 @@ res/cardsfolder/c/compost.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/c/compulsion.txt svneol=native#text/plain
|
res/cardsfolder/c/compulsion.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/compulsive_research.txt svneol=native#text/plain
|
res/cardsfolder/c/compulsive_research.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/concentrate.txt svneol=native#text/plain
|
res/cardsfolder/c/concentrate.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/c/concerted_effort.txt -text
|
||||||
res/cardsfolder/c/conch_horn.txt svneol=native#text/plain
|
res/cardsfolder/c/conch_horn.txt svneol=native#text/plain
|
||||||
res/cardsfolder/c/conclave_equenaut.txt -text
|
res/cardsfolder/c/conclave_equenaut.txt -text
|
||||||
res/cardsfolder/c/conclave_phalanx.txt -text
|
res/cardsfolder/c/conclave_phalanx.txt -text
|
||||||
@@ -2414,6 +2416,7 @@ res/cardsfolder/d/death_cultist.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/d/death_denied.txt svneol=native#text/plain
|
res/cardsfolder/d/death_denied.txt svneol=native#text/plain
|
||||||
res/cardsfolder/d/death_grasp.txt svneol=native#text/plain
|
res/cardsfolder/d/death_grasp.txt svneol=native#text/plain
|
||||||
res/cardsfolder/d/death_hood_cobra.txt svneol=native#text/plain
|
res/cardsfolder/d/death_hood_cobra.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/d/death_mask_duplicant.txt -text
|
||||||
res/cardsfolder/d/death_mutation.txt svneol=native#text/plain
|
res/cardsfolder/d/death_mutation.txt svneol=native#text/plain
|
||||||
res/cardsfolder/d/death_of_a_thousand_stings.txt svneol=native#text/plain
|
res/cardsfolder/d/death_of_a_thousand_stings.txt svneol=native#text/plain
|
||||||
res/cardsfolder/d/death_or_glory.txt -text
|
res/cardsfolder/d/death_or_glory.txt -text
|
||||||
|
|||||||
9
res/cardsfolder/c/cairn_wanderer.txt
Normal file
9
res/cardsfolder/c/cairn_wanderer.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Cairn Wanderer
|
||||||
|
ManaCost:4 B
|
||||||
|
Types:Creature Shapeshifter
|
||||||
|
PT:4/4
|
||||||
|
S:Mode$ Continuous | EffectZone$ All | Affected$ Card.Self | CharacteristicDefining$ True | AddType$ AllCreatureTypes | Description$ Changeling (This card is every creature type at all times.)
|
||||||
|
S:Mode$ Continuous | EffectZone$ All | Affected$ Card.Self | CharacteristicDefining$ True | AddKeyword$ Flying & Fear & First Strike & Double Strike & Deathtouch & Haste & Landwalk & Lifelink & Protection & Reach & Trample & Shroud & Vigilance | SharedKeywordsZone$ Graveyard | SharedRestrictions$ Creature | Description$ As long as a creature card with flying is in a graveyard, CARDNAME has flying. The same is true for fear, first strike, double strike, deathtouch, haste, landwalk, lifelink, protection, reach, trample, shroud, and vigilance.
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/cairn_wanderer.jpg
|
||||||
|
Oracle:Changeling (This card is every creature type at all times.)\nAs long as a creature card with flying is in a graveyard, Cairn Wanderer has flying. The same is true for fear, first strike, double strike, deathtouch, haste, landwalk, lifelink, protection, reach, trample, shroud, and vigilance.
|
||||||
|
SetInfo:LRW Rare
|
||||||
8
res/cardsfolder/c/concerted_effort.txt
Normal file
8
res/cardsfolder/c/concerted_effort.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Concerted Effort
|
||||||
|
ManaCost:2 W W
|
||||||
|
Types:Enchantment
|
||||||
|
T:Mode$ Phase | Phase$ Upkeep | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ At the beginning of each upkeep, all creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance.
|
||||||
|
SVar:TrigPump:AB$ PumpAll | Cost$ 0 | ValidCards$ Creature.YouCtrl | KW$ Flying & Fear & First Strike & Double Strike & Landwalk & Protection & Trample & Vigilance | SharedKeywordsZone$ Battlefield | SharedRestrictions$ Creature.YouCtrl
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/concerted_effort.jpg
|
||||||
|
Oracle:At the beginning of each upkeep, all creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance.
|
||||||
|
SetInfo:RAV Rare
|
||||||
12
res/cardsfolder/d/death_mask_duplicant.txt
Normal file
12
res/cardsfolder/d/death_mask_duplicant.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Death-Mask Duplicant
|
||||||
|
ManaCost:7
|
||||||
|
Types:Artifact Creature Shapeshifter
|
||||||
|
PT:5/5
|
||||||
|
A:AB$ ChangeZone | PrecostDesc$ Imprint - | Cost$ 1 | Imprint$ True | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature.YouOwn | SpellDescription$ Exile target creature card from your graveyard.
|
||||||
|
S:Mode$ Continuous | EffectZone$ All | Affected$ Card.Self | CharacteristicDefining$ True | AddKeyword$ Flying & Fear & First Strike & Double Strike & Haste & Landwalk & Protection & Trample | SharedKeywordsZone$ Exile | SharedRestrictions$ Card.IsImprinted | Description$ As long as a card exiled with CARDNAME has flying, CARDNAME has flying. The same is true for fear, first strike, double strike, haste, landwalk, protection, and trample.
|
||||||
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Any | Execute$ TrigForget | Static$ True
|
||||||
|
SVar:TrigForget:DB$ Cleanup | ClearImprinted$ True
|
||||||
|
SVar:RemAIDeck:True
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/death_mask_duplicant.jpg
|
||||||
|
Oracle:Imprint - {1}: Exile target creature card from your graveyard.\nAs long as a card exiled with Death-Mask Duplicant has flying, Death-Mask Duplicant has flying. The same is true for fear, first strike, double strike, haste, landwalk, protection, and trample.
|
||||||
|
SetInfo:DST Uncommon
|
||||||
@@ -9,11 +9,70 @@ import forge.Command;
|
|||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.ability.AbilityUtils;
|
import forge.card.ability.AbilityUtils;
|
||||||
import forge.card.ability.SpellAbilityEffect;
|
import forge.card.ability.SpellAbilityEffect;
|
||||||
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
public class PumpAllEffect extends SpellAbilityEffect {
|
public class PumpAllEffect extends SpellAbilityEffect {
|
||||||
|
private void applyPumpAll(final SpellAbility sa, final List<Card> list, final int a,
|
||||||
|
final int d, final List<String> keywords, final ArrayList<ZoneType> affectedZones) {
|
||||||
|
|
||||||
|
for (final Card tgtC : list) {
|
||||||
|
|
||||||
|
// only pump things in the affected zones.
|
||||||
|
boolean found = false;
|
||||||
|
for (final ZoneType z : affectedZones) {
|
||||||
|
if (tgtC.isInZone(z)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tgtC.addTempAttackBoost(a);
|
||||||
|
tgtC.addTempDefenseBoost(d);
|
||||||
|
|
||||||
|
for (int i = 0; i < keywords.size(); i++) {
|
||||||
|
tgtC.addExtrinsicKeyword(keywords.get(i));
|
||||||
|
if (keywords.get(i).equals("Suspend")) {
|
||||||
|
tgtC.setSuspend(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("RememberAllPumped")) {
|
||||||
|
sa.getSourceCard().addRemembered(tgtC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sa.hasParam("Permanent")) {
|
||||||
|
// If not Permanent, remove Pumped at EOT
|
||||||
|
final Command untilEOT = new Command() {
|
||||||
|
private static final long serialVersionUID = 5415795460189457660L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
tgtC.addTempAttackBoost(-1 * a);
|
||||||
|
tgtC.addTempDefenseBoost(-1 * d);
|
||||||
|
|
||||||
|
if (keywords.size() > 0) {
|
||||||
|
for (int i = 0; i < keywords.size(); i++) {
|
||||||
|
tgtC.removeExtrinsicKeyword(keywords.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (sa.hasParam("UntilUntaps")) {
|
||||||
|
sa.getSourceCard().addUntapCommand(untilEOT);
|
||||||
|
} else if (sa.hasParam("UntilEndOfCombat")) {
|
||||||
|
Singletons.getModel().getGame().getEndOfCombat().addUntil(untilEOT);
|
||||||
|
} else {
|
||||||
|
Singletons.getModel().getGame().getEndOfTurn().addUntil(untilEOT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected String getStackDescription(SpellAbility sa) {
|
protected String getStackDescription(SpellAbility sa) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
@@ -65,65 +124,16 @@ public class PumpAllEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
list = AbilityUtils.filterListByType(list, valid, sa);
|
list = AbilityUtils.filterListByType(list, valid, sa);
|
||||||
|
|
||||||
final List<String> keywords = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & ")) : new ArrayList<String>();
|
List<String> keywords = sa.hasParam("KW") ? Arrays.asList(sa.getParam("KW").split(" & ")) : new ArrayList<String>();
|
||||||
final int a = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumAtt"), sa);
|
final int a = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumAtt"), sa);
|
||||||
final int d = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumDef"), sa);
|
final int d = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumDef"), sa);
|
||||||
final String remember = sa.getParam("RememberAllPumped");
|
|
||||||
|
|
||||||
for (final Card tgtC : list) {
|
if (sa.hasParam("SharedKeywordsZone")) {
|
||||||
|
List<ZoneType> zones = ZoneType.listValueOf(sa.getParam("SharedKeywordsZone"));
|
||||||
// only pump things in the affected zones.
|
String[] restrictions = sa.hasParam("SharedRestrictions") ? sa.getParam("SharedRestrictions").split(",") : new String[] {"Card"};
|
||||||
boolean found = false;
|
keywords = CardFactoryUtil.sharedKeywords(sa.getParam("KW").split(" & "), restrictions, zones, sa.getSourceCard());
|
||||||
for (final ZoneType z : affectedZones) {
|
|
||||||
if (tgtC.isInZone(z)) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tgtC.addTempAttackBoost(a);
|
|
||||||
tgtC.addTempDefenseBoost(d);
|
|
||||||
|
|
||||||
for (int i = 0; i < keywords.size(); i++) {
|
|
||||||
tgtC.addExtrinsicKeyword(keywords.get(i));
|
|
||||||
if (keywords.get(i).equals("Suspend")) {
|
|
||||||
tgtC.setSuspend(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remember != null) {
|
|
||||||
sa.getSourceCard().addRemembered(tgtC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sa.hasParam("Permanent")) {
|
|
||||||
// If not Permanent, remove Pumped at EOT
|
|
||||||
final Command untilEOT = new Command() {
|
|
||||||
private static final long serialVersionUID = 5415795460189457660L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
tgtC.addTempAttackBoost(-1 * a);
|
|
||||||
tgtC.addTempDefenseBoost(-1 * d);
|
|
||||||
|
|
||||||
if (keywords.size() > 0) {
|
|
||||||
for (int i = 0; i < keywords.size(); i++) {
|
|
||||||
tgtC.removeExtrinsicKeyword(keywords.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (sa.hasParam("UntilUntaps")) {
|
|
||||||
sa.getSourceCard().addUntapCommand(untilEOT);
|
|
||||||
} else if (sa.hasParam("UntilEndOfCombat")) {
|
|
||||||
Singletons.getModel().getGame().getEndOfCombat().addUntil(untilEOT);
|
|
||||||
} else {
|
|
||||||
Singletons.getModel().getGame().getEndOfTurn().addUntil(untilEOT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.applyPumpAll(sa, list, a, d, keywords, affectedZones);
|
||||||
} // pumpAllResolve()
|
} // pumpAllResolve()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2171,6 +2171,53 @@ public class CardFactoryUtil {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* sharedKeywords.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param kw
|
||||||
|
* a {@link forge.CardList} object.
|
||||||
|
* @return a List<String>.
|
||||||
|
*/
|
||||||
|
public static List<String> sharedKeywords(final String[] kw, final String[] restrictions,
|
||||||
|
final List<ZoneType> zones, final Card host) {
|
||||||
|
final List<String> filteredkw = new ArrayList<String>();
|
||||||
|
final Player p = host.getController();
|
||||||
|
List<Card> cardlist = new ArrayList<Card>(p.getGame().getCardsIn(zones));
|
||||||
|
final List<String> landkw = new ArrayList<String>();
|
||||||
|
final List<String> protectionkw = new ArrayList<String>();
|
||||||
|
final List<String> allkw = new ArrayList<String>();
|
||||||
|
|
||||||
|
cardlist = CardLists.getValidCards(cardlist, restrictions, p, host);
|
||||||
|
for (Card c : cardlist) {
|
||||||
|
for (String k : c.getKeyword()) {
|
||||||
|
if (k.endsWith("walk")) {
|
||||||
|
if (!landkw.contains(k)) {
|
||||||
|
landkw.add(k);
|
||||||
|
}
|
||||||
|
} else if (k.startsWith("Protection")) {
|
||||||
|
if (!protectionkw.contains(k)) {
|
||||||
|
protectionkw.add(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allkw.contains(k)) {
|
||||||
|
allkw.add(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String keyword : kw) {
|
||||||
|
if (keyword.equals("Protection")) {
|
||||||
|
filteredkw.addAll(protectionkw);
|
||||||
|
} else if (keyword.equals("Landwalk")) {
|
||||||
|
filteredkw.addAll(landkw);
|
||||||
|
} else if (allkw.contains(keyword)) {
|
||||||
|
filteredkw.add(keyword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredkw;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* getBushidoEffects.
|
* getBushidoEffects.
|
||||||
|
|||||||
@@ -160,6 +160,12 @@ public class StaticAbilityContinuous {
|
|||||||
addKeywords[w] = addKeywords[w].replaceAll("ChosenName", "Card.named" + chosenName);
|
addKeywords[w] = addKeywords[w].replaceAll("ChosenName", "Card.named" + chosenName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (params.containsKey("SharedKeywordsZone")) {
|
||||||
|
List<ZoneType> zones = ZoneType.listValueOf(params.get("SharedKeywordsZone"));
|
||||||
|
String[] restrictions = params.containsKey("SharedRestrictions") ? params.get("SharedRestrictions").split(",") : new String[] {"Card"};
|
||||||
|
List<String> kw = CardFactoryUtil.sharedKeywords(addKeywords, restrictions, zones, hostCard);
|
||||||
|
addKeywords = kw.toArray(new String[kw.size()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddHiddenKeyword")) {
|
if (params.containsKey("AddHiddenKeyword")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user