mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
- Added Infinite Reflection
- Converted Essence of the Wild to script - added ImageSource parameter to CloneEffect - some small checkstyle fixed
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -5226,6 +5226,7 @@ res/cardsfolder/i/infiltration_lens.txt svneol=native#text/plain
|
||||
res/cardsfolder/i/infiltrator_il_kor.txt svneol=native#text/plain
|
||||
res/cardsfolder/i/infiltrators_magemark.txt -text
|
||||
res/cardsfolder/i/infinite_hourglass.txt -text
|
||||
res/cardsfolder/i/infinite_reflection.txt -text
|
||||
res/cardsfolder/i/inflame.txt svneol=native#text/plain
|
||||
res/cardsfolder/i/information_dealer.txt svneol=native#text/plain
|
||||
res/cardsfolder/i/infuse.txt svneol=native#text/plain
|
||||
|
||||
@@ -2,6 +2,8 @@ Name:Essence of the Wild
|
||||
ManaCost:3 G G G
|
||||
Types:Creature Avatar
|
||||
PT:6/6
|
||||
K:ETBReplacement:Copy:EssenceClone:Mandatory:Battlefield:Creature.YouCtrl
|
||||
SVar:EssenceClone:DB$ Clone | Defined$ Self | CloneTarget$ ReplacedCard | SpellDescription$ Creatures you control enter the battlefield as a copy of CARDNAME.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/essence_of_the_wild.jpg
|
||||
Oracle:Creatures you control enter the battlefield as a copy of Essence of the Wild.
|
||||
SetInfo:ISD Mythic
|
||||
16
res/cardsfolder/i/infinite_reflection.txt
Normal file
16
res/cardsfolder/i/infinite_reflection.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
Name:Infinite Reflection
|
||||
ManaCost:5 U
|
||||
Types:Enchantment Aura
|
||||
K:Enchant creature
|
||||
A:SP$ Attach | Cost$ 5 U | ValidTgts$ Creature | AILogic$ HighestEvaluation
|
||||
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ RememberInitialAttach | Static$ True
|
||||
SVar:RememberInitialAttach:DB$ Pump | RememberObjects$ Valid Card.AttachedBy
|
||||
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ FirstReflections | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature.
|
||||
SVar:FirstReflections:DB$ RepeatEach | RepeatCards$ Creature.nonToken+YouCtrl | UseImprinted$ True | Zone$ Battlefield | RepeatSubAbility$ Reflect | SubAbility$ DBCleanup
|
||||
SVar:Reflect:DB$ Clone | Defined$ Remembered | CloneTarget$ Imprinted | ImageSource$ Remembered
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
K:ETBReplacement:Copy:Reflections:Mandatory:Battlefield:Creature.nonToken+YouCtrl
|
||||
SVar:Reflections:DB$ Clone | Defined$ Enchanted | CloneTarget$ ReplacedCard | ImageSource$ Enchanted | SpellDescription$ Nontoken creatures you control enter the battlefield as a copy of enchanted creature.
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/infinite_reflection.jpg
|
||||
Oracle:Enchant creature\nWhen Infinite Reflection enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature.\nNontoken creatures you control enter the battlefield as a copy of enchanted creature.
|
||||
SetInfo:AVR Rare
|
||||
@@ -352,7 +352,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach ai control preference.
|
||||
* Attach ai reanimate preference.
|
||||
*
|
||||
* @param sa
|
||||
* the sa
|
||||
@@ -380,7 +380,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach ai control preference.
|
||||
* Attach ai specific card preference.
|
||||
*
|
||||
* @param sa
|
||||
* the sa
|
||||
@@ -463,6 +463,16 @@ public class AttachAi extends SpellAbilityAi {
|
||||
return acceptableChoice(c, mandatory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach ai highest evaluated preference.
|
||||
*
|
||||
* @param list the initial valid list
|
||||
* @return the card
|
||||
*/
|
||||
private static Card attachAIHighestEvaluationPreference(final List<Card> list) {
|
||||
return ComputerUtilCard.getBestAI(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach ai curse preference.
|
||||
*
|
||||
@@ -947,6 +957,8 @@ public class AttachAi extends SpellAbilityAi {
|
||||
c = attachAIReanimatePreference(sa, prefList, mandatory, attachSource);
|
||||
} else if ("SpecificCard".equals(logic)) {
|
||||
c = attachAISpecificCardPreference(sa, prefList, mandatory, attachSource);
|
||||
} else if ("HighestEvaluation".equals(logic)) {
|
||||
c = attachAIHighestEvaluationPreference(prefList);
|
||||
}
|
||||
|
||||
return c;
|
||||
|
||||
@@ -86,7 +86,12 @@ public class CloneEffect extends SpellAbilityEffect {
|
||||
tgtCard = cloneTargets.get(0);
|
||||
}
|
||||
|
||||
// determine the image to be used for the clone
|
||||
String imageFileName = host.getImageKey();
|
||||
List<Card> cloneImgSources = AbilityUtils.getDefinedCards(host, sa.getParam("ImageSource"), sa);
|
||||
if (!cloneImgSources.isEmpty()) {
|
||||
imageFileName = cloneImgSources.get(0).getImageKey();
|
||||
}
|
||||
|
||||
boolean keepName = sa.hasParam("KeepName");
|
||||
String originalName = tgtCard.getName();
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardCharacteristicName;
|
||||
import forge.CardLists;
|
||||
import forge.CardPredicates;
|
||||
import forge.CardPredicates.Presets;
|
||||
@@ -37,9 +36,6 @@ import forge.Singletons;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.replacement.ReplacementEffect;
|
||||
import forge.card.replacement.ReplacementHandler;
|
||||
import forge.card.replacement.ReplacementLayer;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilityStatic;
|
||||
@@ -687,47 +683,6 @@ public class CardFactoryCreatures {
|
||||
card.addSpellAbility(finalAb);
|
||||
}
|
||||
|
||||
private static void getCard_EssenceOfTheWild(final Card card) {
|
||||
class EOTWReplacement extends Ability {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param sourceCard
|
||||
* @param manaCost
|
||||
*/
|
||||
public EOTWReplacement(Card sourceCard, ManaCost manaCost) {
|
||||
super(sourceCard, manaCost);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.SpellAbility#resolve()
|
||||
*/
|
||||
@Override
|
||||
public void resolve() {
|
||||
Card movedCard = (Card) this.getReplacingObject("Card");
|
||||
if (movedCard.isCloned()) { // cloning again
|
||||
movedCard.switchStates(CardCharacteristicName.Cloner, CardCharacteristicName.Original);
|
||||
movedCard.setState(CardCharacteristicName.Original);
|
||||
movedCard.clearStates(CardCharacteristicName.Cloner);
|
||||
}
|
||||
movedCard.addAlternateState(CardCharacteristicName.Cloner);
|
||||
movedCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner);
|
||||
movedCard.setState(CardCharacteristicName.Original);
|
||||
movedCard.getCharacteristics().copy(this.getSourceCard().getCharacteristics());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SpellAbility repAb = new EOTWReplacement(card, ManaCost.ZERO);
|
||||
CardFactoryUtil.setupETBReplacementAbility(repAb);
|
||||
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement("Event$ Moved | ValidCard$ Creature.Other+YouCtrl | Destination$ Battlefield | ActiveZones$ Battlefield | Description$ Creatures you control enter the battlefield as copies of CARDNAME.", card);
|
||||
re.setLayer(ReplacementLayer.Copy);
|
||||
re.setOverridingAbility(repAb);
|
||||
|
||||
card.addReplacementEffect(re);
|
||||
}
|
||||
|
||||
// // This is a hardcoded card template
|
||||
//
|
||||
// private static void getCard_(final Card card, final String cardName) {
|
||||
@@ -754,8 +709,6 @@ public class CardFactoryCreatures {
|
||||
} else if (cardName.equals("Duct Crawler") || cardName.equals("Shrewd Hatchling")
|
||||
|| cardName.equals("Spin Engine") || cardName.equals("Screeching Griffin")) {
|
||||
getCard_DuctCrawler(card, cardName);
|
||||
} else if (cardName.equals("Essence of the Wild")) {
|
||||
getCard_EssenceOfTheWild(card);
|
||||
}
|
||||
|
||||
// ***************************************************
|
||||
|
||||
@@ -659,13 +659,13 @@ public class CardFactoryUtil {
|
||||
*/
|
||||
public static int getNumberOfManaSymbolsByColor(final String colorAbb, final List<Card> cards) {
|
||||
int count = 0;
|
||||
for(Card c : cards) {
|
||||
for (Card c : cards) {
|
||||
// Certain tokens can have mana cost, so don't skip them
|
||||
count += CardFactoryUtil.getNumberOfManaSymbolsByColor(colorAbb, c);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getNumberOfManaSymbolsByColor.
|
||||
@@ -1174,7 +1174,7 @@ public class CardFactoryUtil {
|
||||
return CardFactoryUtil.doXMath(players.get(0).getLifeLostThisTurn(), m, source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sq[0].contains("PoisonCounters")) {
|
||||
if (players.size() > 0) {
|
||||
return CardFactoryUtil.doXMath(players.get(0).getPoisonCounters(), m, source);
|
||||
@@ -2134,19 +2134,19 @@ public class CardFactoryUtil {
|
||||
if (sq[0].equals("Random")) {
|
||||
int min = 0;
|
||||
int max = 0;
|
||||
|
||||
|
||||
if (StringUtils.isNumeric(sq[1])) {
|
||||
min = Integer.parseInt(sq[1]);
|
||||
} else {
|
||||
min = CardFactoryUtil.xCount(c, c.getSVar(sq[1]));
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isNumeric(sq[2])) {
|
||||
max = Integer.parseInt(sq[2]);
|
||||
} else {
|
||||
max = CardFactoryUtil.xCount(c, c.getSVar(sq[2]));
|
||||
}
|
||||
|
||||
|
||||
return forge.util.MyRandom.getRandom().nextInt(max) + min;
|
||||
}
|
||||
|
||||
@@ -2568,7 +2568,7 @@ public class CardFactoryUtil {
|
||||
|
||||
final SpellAbility sa = card.getSpellAbility()[0];
|
||||
sa.setIsMultiKicker(true);
|
||||
sa.setMultiKickerManaCost(new ManaCost( new ManaCostParser(k[1])));
|
||||
sa.setMultiKickerManaCost(new ManaCost(new ManaCostParser(k[1])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2651,36 +2651,36 @@ public class CardFactoryUtil {
|
||||
if (championPos != -1) {
|
||||
String parse = card.getKeyword().get(championPos);
|
||||
card.removeIntrinsicKeyword(parse);
|
||||
|
||||
|
||||
final String[] k = parse.split(":");
|
||||
final String[] valid = k[1].split(",");
|
||||
String desc = k.length > 2 ? k[2] : k[1];
|
||||
|
||||
|
||||
StringBuilder changeType = new StringBuilder();
|
||||
for(String v : valid) {
|
||||
for (String v : valid) {
|
||||
if (changeType.length() != 0) {
|
||||
changeType.append(",");
|
||||
}
|
||||
changeType.append(v).append(".YouCtrl+Other");
|
||||
}
|
||||
|
||||
|
||||
StringBuilder trig = new StringBuilder();
|
||||
trig.append("Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | ");
|
||||
trig.append("Execute$ ChampionAbility | TriggerDescription$ Champion a(n) ");
|
||||
trig.append(desc).append(" (When this enters the battlefield, sacrifice it unless you exile another ");
|
||||
trig.append(desc).append(" you control. When this leaves the battlefield, that card returns to the battlefield.)");
|
||||
|
||||
|
||||
StringBuilder trigReturn = new StringBuilder();
|
||||
trigReturn.append("Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | ");
|
||||
trigReturn.append("Execute$ ChampionReturn | Secondary$ True | TriggerDescription$ When this leaves the battlefield, that card returns to the battlefield.");
|
||||
|
||||
|
||||
StringBuilder ab = new StringBuilder();
|
||||
ab.append("DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | Champion$ True | ");
|
||||
ab.append("Hidden$ True | Optional$ True | SubAbility$ DBSacrifice | ChangeType$ ").append(changeType);
|
||||
|
||||
|
||||
StringBuilder subAb = new StringBuilder();
|
||||
subAb.append("DB$ Sacrifice | Defined$ Card.Self | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0");
|
||||
|
||||
|
||||
String returnChampion = "DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield";
|
||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig.toString(), card, true);
|
||||
final Trigger parsedTrigReturn = TriggerHandler.parseTrigger(trigReturn.toString(), card, true);
|
||||
@@ -2690,7 +2690,7 @@ public class CardFactoryUtil {
|
||||
card.setSVar("ChampionReturn", returnChampion);
|
||||
card.setSVar("DBSacrifice", subAb.toString());
|
||||
}
|
||||
|
||||
|
||||
final int echoPos = CardFactoryUtil.hasKeyword(card, "Echo");
|
||||
if (echoPos != -1) {
|
||||
// card.removeIntrinsicKeyword(parse);
|
||||
@@ -2966,14 +2966,23 @@ public class CardFactoryUtil {
|
||||
String desc = repAb.getDescription();
|
||||
setupETBReplacementAbility(repAb);
|
||||
|
||||
String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | Description$ " + desc;
|
||||
if (splitkw.length == 4) {
|
||||
final String valid = splitkw.length >= 6 ? splitkw[5] : "Card.Self";
|
||||
|
||||
StringBuilder repEffsb = new StringBuilder();
|
||||
repEffsb.append("Event$ Moved | ValidCard$ ").append(valid);
|
||||
repEffsb.append(" | Destination$ Battlefield | Description$ ").append(desc);
|
||||
if (splitkw.length >= 4) {
|
||||
if (splitkw[3].contains("Optional")) {
|
||||
repeffstr += " | Optional$ True";
|
||||
repEffsb.append(" | Optional$ True");
|
||||
}
|
||||
}
|
||||
if (splitkw.length >= 5) {
|
||||
if (!splitkw[4].isEmpty()) {
|
||||
repEffsb.append(" | ActiveZones$ " + splitkw[4]);
|
||||
}
|
||||
}
|
||||
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card);
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(repEffsb.toString(), card);
|
||||
re.setLayer(layer);
|
||||
re.setOverridingAbility(repAb);
|
||||
|
||||
@@ -3085,7 +3094,7 @@ public class CardFactoryUtil {
|
||||
if (card.getController().isHuman()) {
|
||||
game.getActionPlay().playSpellAbilityNoStack(card.getController(), origSA, false);
|
||||
} else {
|
||||
ComputerUtil.playNoStack((AIPlayer)card.getController(), origSA, game);
|
||||
ComputerUtil.playNoStack((AIPlayer) card.getController(), origSA, game);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -3142,7 +3151,7 @@ public class CardFactoryUtil {
|
||||
};
|
||||
haunterDiesWork.setDescription(hauntDescription);
|
||||
|
||||
final InputSelectManyCards target = new InputSelectManyCards(1,1) {
|
||||
final InputSelectManyCards target = new InputSelectManyCards(1, 1) {
|
||||
private static final long serialVersionUID = 1981791992623774490L;
|
||||
|
||||
@Override
|
||||
@@ -3160,7 +3169,7 @@ public class CardFactoryUtil {
|
||||
}
|
||||
return c.canBeTargetedBy(haunterDiesWork);
|
||||
}
|
||||
};
|
||||
};
|
||||
target.setMessage("Choose target creature to haunt.");
|
||||
|
||||
final Ability haunterDiesSetup = new Ability(card, ManaCost.ZERO) {
|
||||
|
||||
Reference in New Issue
Block a user