mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Merge branch 'differentColors' into 'master'
Add Different colors to combo mana See merge request core-developers/forge!1600
This commit is contained in:
@@ -41,6 +41,7 @@ public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte>, Ser
|
|||||||
private static final long serialVersionUID = 794691267379929080L;
|
private static final long serialVersionUID = 794691267379929080L;
|
||||||
|
|
||||||
private final byte myColor;
|
private final byte myColor;
|
||||||
|
public byte getMyColor() { return myColor; }
|
||||||
private final float orderWeight;
|
private final float orderWeight;
|
||||||
|
|
||||||
private static final ColorSet[] cache = new ColorSet[32];
|
private static final ColorSet[] cache = new ColorSet[32];
|
||||||
|
|||||||
@@ -58,120 +58,132 @@ public class ManaEffect extends SpellAbilityEffect {
|
|||||||
if (abMana.isComboMana()) {
|
if (abMana.isComboMana()) {
|
||||||
for (Player p : tgtPlayers) {
|
for (Player p : tgtPlayers) {
|
||||||
int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1;
|
int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1;
|
||||||
if (tgt == null || p.canBeTargetedBy(sa)) {
|
if (tgt != null && !p.canBeTargetedBy(sa)) {
|
||||||
Player activator = sa.getActivatingPlayer();
|
// Illegal target. Skip.
|
||||||
String express = abMana.getExpressChoice();
|
continue;
|
||||||
String[] colorsProduced = abMana.getComboColors().split(" ");
|
|
||||||
|
|
||||||
final StringBuilder choiceString = new StringBuilder();
|
|
||||||
ColorSet colorOptions = null;
|
|
||||||
String[] colorsNeeded = express.isEmpty() ? null : express.split(" ");
|
|
||||||
if (!abMana.isAnyMana()) {
|
|
||||||
colorOptions = ColorSet.fromNames(colorsProduced);
|
|
||||||
} else {
|
|
||||||
colorOptions = ColorSet.fromNames(MagicColor.Constant.ONLY_COLORS);
|
|
||||||
}
|
|
||||||
final ColorSet fullOptions = colorOptions;
|
|
||||||
for (int nMana = 1; nMana <= amount; nMana++) {
|
|
||||||
String choice = "";
|
|
||||||
if (colorsNeeded != null && colorsNeeded.length >= nMana) { // select from express choices if possible
|
|
||||||
colorOptions = ColorSet
|
|
||||||
.fromMask(fullOptions.getColor() & ManaAtom.fromName(colorsNeeded[nMana - 1]));
|
|
||||||
}
|
|
||||||
if (colorOptions.isColorless() && colorsProduced.length > 0) {
|
|
||||||
// If we just need generic mana, no reason to ask the controller for a choice,
|
|
||||||
// just use the first possible color.
|
|
||||||
choice = colorsProduced[0];
|
|
||||||
} else {
|
|
||||||
byte chosenColor = activator.getController().chooseColor("Select Mana to Produce", sa, colorOptions);
|
|
||||||
if (chosenColor == 0)
|
|
||||||
throw new RuntimeException("ManaEffect::resolve() /*combo mana*/ - " + activator + " color mana choice is empty for " + card.getName());
|
|
||||||
choice = MagicColor.toShortString(chosenColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nMana != 1) {
|
|
||||||
choiceString.append(" ");
|
|
||||||
}
|
|
||||||
choiceString.append(choice);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (choiceString.toString().isEmpty() && "Combo ColorIdentity".equals(abMana.getOrigProduced())) {
|
|
||||||
// No mana could be produced here (non-EDH match?), so cut short
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game.action.nofityOfValue(sa, card, activator + " picked " + choiceString, activator);
|
|
||||||
abMana.setExpressChoice(choiceString.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player activator = sa.getActivatingPlayer();
|
||||||
|
String express = abMana.getExpressChoice();
|
||||||
|
String[] colorsProduced = abMana.getComboColors().split(" ");
|
||||||
|
|
||||||
|
final StringBuilder choiceString = new StringBuilder();
|
||||||
|
ColorSet colorOptions = null;
|
||||||
|
String[] colorsNeeded = express.isEmpty() ? null : express.split(" ");
|
||||||
|
if (!abMana.isAnyMana()) {
|
||||||
|
colorOptions = ColorSet.fromNames(colorsProduced);
|
||||||
|
} else {
|
||||||
|
colorOptions = ColorSet.fromNames(MagicColor.Constant.ONLY_COLORS);
|
||||||
|
}
|
||||||
|
boolean differentChoice = abMana.getOrigProduced().contains("Different");
|
||||||
|
ColorSet fullOptions = colorOptions;
|
||||||
|
for (int nMana = 0; nMana < amount; nMana++) {
|
||||||
|
String choice = "";
|
||||||
|
if (colorsNeeded != null && colorsNeeded.length > nMana) { // select from express choices if possible
|
||||||
|
colorOptions = ColorSet
|
||||||
|
.fromMask(fullOptions.getColor() & ManaAtom.fromName(colorsNeeded[nMana]));
|
||||||
|
}
|
||||||
|
if (colorOptions.isColorless() && colorsProduced.length > 0) {
|
||||||
|
// If we just need generic mana, no reason to ask the controller for a choice,
|
||||||
|
// just use the first possible color.
|
||||||
|
choice = colorsProduced[differentChoice ? nMana : 0];
|
||||||
|
} else {
|
||||||
|
byte chosenColor = activator.getController().chooseColor("Select Mana to Produce", sa, colorOptions);
|
||||||
|
if (chosenColor == 0)
|
||||||
|
throw new RuntimeException("ManaEffect::resolve() /*combo mana*/ - " + activator + " color mana choice is empty for " + card.getName());
|
||||||
|
|
||||||
|
fullOptions = ColorSet.fromMask(fullOptions.getMyColor() - chosenColor);
|
||||||
|
choice = MagicColor.toShortString(chosenColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nMana > 0) {
|
||||||
|
choiceString.append(" ");
|
||||||
|
}
|
||||||
|
choiceString.append(choice);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (choiceString.toString().isEmpty() && "Combo ColorIdentity".equals(abMana.getOrigProduced())) {
|
||||||
|
// No mana could be produced here (non-EDH match?), so cut short
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game.action.nofityOfValue(sa, card, activator + " picked " + choiceString, activator);
|
||||||
|
abMana.setExpressChoice(choiceString.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (abMana.isAnyMana()) {
|
else if (abMana.isAnyMana()) {
|
||||||
for (Player p : tgtPlayers) {
|
for (Player p : tgtPlayers) {
|
||||||
if (tgt == null || p.canBeTargetedBy(sa)) {
|
if (tgt != null && !p.canBeTargetedBy(sa)) {
|
||||||
Player act = sa.getActivatingPlayer();
|
// Illegal target. Skip.
|
||||||
// AI color choice is set in ComputerUtils so only human players need to make a choice
|
continue;
|
||||||
|
|
||||||
String colorsNeeded = abMana.getExpressChoice();
|
|
||||||
String choice = "";
|
|
||||||
|
|
||||||
ColorSet colorMenu = null;
|
|
||||||
byte mask = 0;
|
|
||||||
//loop through colors to make menu
|
|
||||||
for (int nChar = 0; nChar < colorsNeeded.length(); nChar++) {
|
|
||||||
mask |= MagicColor.fromName(colorsNeeded.charAt(nChar));
|
|
||||||
}
|
|
||||||
colorMenu = mask == 0 ? ColorSet.ALL_COLORS : ColorSet.fromMask(mask);
|
|
||||||
byte val = p.getController().chooseColor("Select Mana to Produce", sa, colorMenu);
|
|
||||||
if (0 == val) {
|
|
||||||
throw new RuntimeException("ManaEffect::resolve() /*any mana*/ - " + act + " color mana choice is empty for " + card.getName());
|
|
||||||
}
|
|
||||||
choice = MagicColor.toShortString(val);
|
|
||||||
|
|
||||||
game.action.nofityOfValue(sa, card, act + " picked " + choice, act);
|
|
||||||
abMana.setExpressChoice(choice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player act = sa.getActivatingPlayer();
|
||||||
|
// AI color choice is set in ComputerUtils so only human players need to make a choice
|
||||||
|
|
||||||
|
String colorsNeeded = abMana.getExpressChoice();
|
||||||
|
String choice = "";
|
||||||
|
|
||||||
|
ColorSet colorMenu = null;
|
||||||
|
byte mask = 0;
|
||||||
|
//loop through colors to make menu
|
||||||
|
for (int nChar = 0; nChar < colorsNeeded.length(); nChar++) {
|
||||||
|
mask |= MagicColor.fromName(colorsNeeded.charAt(nChar));
|
||||||
|
}
|
||||||
|
colorMenu = mask == 0 ? ColorSet.ALL_COLORS : ColorSet.fromMask(mask);
|
||||||
|
byte val = p.getController().chooseColor("Select Mana to Produce", sa, colorMenu);
|
||||||
|
if (0 == val) {
|
||||||
|
throw new RuntimeException("ManaEffect::resolve() /*any mana*/ - " + act + " color mana choice is empty for " + card.getName());
|
||||||
|
}
|
||||||
|
choice = MagicColor.toShortString(val);
|
||||||
|
|
||||||
|
game.action.nofityOfValue(sa, card, act + " picked " + choice, act);
|
||||||
|
abMana.setExpressChoice(choice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (abMana.isSpecialMana()) {
|
else if (abMana.isSpecialMana()) {
|
||||||
for (Player p : tgtPlayers) {
|
for (Player p : tgtPlayers) {
|
||||||
if (tgt == null || p.canBeTargetedBy(sa)) {
|
if (tgt != null && !p.canBeTargetedBy(sa)) {
|
||||||
String type = abMana.getOrigProduced().split("Special ")[1];
|
// Illegal target. Skip.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (type.equals("EnchantedManaCost")) {
|
String type = abMana.getOrigProduced().split("Special ")[1];
|
||||||
Card enchanted = card.getEnchantingCard();
|
|
||||||
if (enchanted == null )
|
if (type.equals("EnchantedManaCost")) {
|
||||||
|
Card enchanted = card.getEnchantingCard();
|
||||||
|
if (enchanted == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int generic = enchanted.getManaCost().getGenericCost();
|
||||||
|
if( generic > 0 )
|
||||||
|
sb.append(generic);
|
||||||
|
|
||||||
|
for (ManaCostShard s : enchanted.getManaCost()) {
|
||||||
|
ColorSet cs = ColorSet.fromMask(s.getColorMask());
|
||||||
|
if(cs.isColorless())
|
||||||
continue;
|
continue;
|
||||||
|
sb.append(' ');
|
||||||
StringBuilder sb = new StringBuilder();
|
if (cs.isMonoColor())
|
||||||
int generic = enchanted.getManaCost().getGenericCost();
|
sb.append(MagicColor.toShortString(s.getColorMask()));
|
||||||
if( generic > 0 )
|
else /* (cs.isMulticolor()) */ {
|
||||||
sb.append(generic);
|
byte chosenColor = sa.getActivatingPlayer().getController().chooseColor("Choose a single color from " + s.toString(), sa, cs);
|
||||||
|
sb.append(MagicColor.toShortString(chosenColor));
|
||||||
for (ManaCostShard s : enchanted.getManaCost()) {
|
|
||||||
ColorSet cs = ColorSet.fromMask(s.getColorMask());
|
|
||||||
if(cs.isColorless())
|
|
||||||
continue;
|
|
||||||
sb.append(' ');
|
|
||||||
if (cs.isMonoColor())
|
|
||||||
sb.append(MagicColor.toShortString(s.getColorMask()));
|
|
||||||
else /* (cs.isMulticolor()) */ {
|
|
||||||
byte chosenColor = sa.getActivatingPlayer().getController().chooseColor("Choose a single color from " + s.toString(), sa, cs);
|
|
||||||
sb.append(MagicColor.toShortString(chosenColor));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
abMana.setExpressChoice(sb.toString().trim());
|
|
||||||
} else if (type.equals("LastNotedType")) {
|
|
||||||
Mana manaType = (Mana) Iterables.getFirst(card.getRemembered(), null);
|
|
||||||
if (manaType == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String cs = manaType.toString();
|
|
||||||
abMana.setExpressChoice(cs);
|
|
||||||
}
|
}
|
||||||
|
abMana.setExpressChoice(sb.toString().trim());
|
||||||
|
} else if (type.equals("LastNotedType")) {
|
||||||
|
Mana manaType = (Mana) Iterables.getFirst(card.getRemembered(), null);
|
||||||
|
if (manaType == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String cs = manaType.toString();
|
||||||
|
abMana.setExpressChoice(cs);
|
||||||
|
}
|
||||||
|
|
||||||
if (abMana.getExpressChoice().isEmpty()) {
|
if (abMana.getExpressChoice().isEmpty()) {
|
||||||
System.out.println("AbilityFactoryMana::manaResolve() - special mana effect is empty for " + sa.getHostCard().getName());
|
System.out.println("AbilityFactoryMana::manaResolve() - special mana effect is empty for " + sa.getHostCard().getName());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -431,58 +431,22 @@ public class AbilityManaPart implements java.io.Serializable {
|
|||||||
return this.lastManaProduced;
|
return this.lastManaProduced;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* isSnow.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public final boolean isSnow() {
|
public final boolean isSnow() {
|
||||||
return this.getSourceCard().isSnow();
|
return this.getSourceCard().isSnow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* isAnyMana.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public boolean isAnyMana() {
|
public boolean isAnyMana() {
|
||||||
return this.getOrigProduced().contains("Any");
|
return this.getOrigProduced().contains("Any");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* isComboMana.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public boolean isComboMana() {
|
public boolean isComboMana() {
|
||||||
return this.getOrigProduced().contains("Combo");
|
return this.getOrigProduced().contains("Combo");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* isSpecialMana.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public boolean isSpecialMana() {
|
public boolean isSpecialMana() {
|
||||||
return this.getOrigProduced().contains("Special");
|
return this.getOrigProduced().contains("Special");
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* canProduce.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param s
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public final boolean canProduce(final String s) {
|
public final boolean canProduce(final String s) {
|
||||||
return canProduce(s, null);
|
return canProduce(s, null);
|
||||||
}
|
}
|
||||||
|
|||||||
7
forge-gui/res/cardsfolder/f/firemind_vessel.txt
Normal file
7
forge-gui/res/cardsfolder/f/firemind_vessel.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Firemind Vessel
|
||||||
|
ManaCost:4
|
||||||
|
Types:Artifact
|
||||||
|
K:CARDNAME enters the battlefield tapped.
|
||||||
|
A:AB$ Mana | Cost$ T | Amount$ 2 | Produced$ Combo AnyDifferent | SpellDescription$ Add two mana of different colors.
|
||||||
|
AI:RemoveDeck:All
|
||||||
|
Oracle:Firemind Vessel enters the battlefield tapped.\n{T}: Add two mana of different colors.
|
||||||
9
forge-gui/res/cardsfolder/i/interplanar_beacon.txt
Normal file
9
forge-gui/res/cardsfolder/i/interplanar_beacon.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Interplanar Beacon
|
||||||
|
ManaCost:
|
||||||
|
Types:Land
|
||||||
|
T:Mode$ SpellCast | ValidCard$ Planeswalker | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever you cast a planeswalker spell, you gain 1 life.
|
||||||
|
SVar:TrigGainLife:DB$GainLife | Defined$ You | LifeAmount$ 1
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||||
|
A:AB$ Mana | Cost$ 1 T | Produced$ Combo AnyDifferent | Amount$ 2 | RestrictValid$ Spell.Planeswalker | SpellDescription$ Add two mana of different colors. Spend this mana only to cast planeswalker spells.
|
||||||
|
AI:RemoveDeck:All
|
||||||
|
Oracle:Whenever you cast a planeswalker spell, you gain 1 life.\n{T}: Add {C}.\n{1}, {T}: Add two mana of different colors. Spend this mana only to cast planeswalker spells.
|
||||||
@@ -3,5 +3,6 @@ ManaCost:2
|
|||||||
Types:Artifact
|
Types:Artifact
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw a card.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters the battlefield, draw a card.
|
||||||
SVar:TrigDraw:DB$Draw | Defined$ You | NumCards$ 1
|
SVar:TrigDraw:DB$Draw | Defined$ You | NumCards$ 1
|
||||||
A:AB$ Mana | Cost$ 2 T Sac<1/CARDNAME> | Produced$ Any | Amount$ 2 | SpellDescription$ Add two mana of different colors.
|
A:AB$ Mana | Cost$ 2 T Sac<1/CARDNAME> | Produced$ Combo AnyDifferent | Amount$ 2 | SpellDescription$ Add two mana of different colors.
|
||||||
|
AI:RemoveDeck:All
|
||||||
Oracle:When Guild Globe enters the battlefield, draw a card.\n{2}, {T}, Sacrifice Guild Globe: Add two mana of different colors.
|
Oracle:When Guild Globe enters the battlefield, draw a card.\n{2}, {T}, Sacrifice Guild Globe: Add two mana of different colors.
|
||||||
|
|||||||
Reference in New Issue
Block a user