mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
@@ -1352,7 +1352,7 @@ public class ComputerUtilMana {
|
||||
CostAdjustment.adjust(cost, sa, null, test);
|
||||
|
||||
int timesMultikicked = card.getKickerMagnitude();
|
||||
if (timesMultikicked > 0 && sa.hasParam("Announce") && sa.getParam("Announce").startsWith("Multikicker")) {
|
||||
if (timesMultikicked > 0 && sa.isAnnouncing("Multikicker")) {
|
||||
ManaCost mkCost = sa.getMultiKickerManaCost();
|
||||
for (int i = 0; i < timesMultikicked; i++) {
|
||||
cost.addManaCost(mkCost);
|
||||
|
||||
@@ -153,8 +153,7 @@ public class PermanentAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sa.hasParam("Announce") && sa.getParam("Announce").startsWith("Multikicker")) {
|
||||
// String announce = sa.getParam("Announce");
|
||||
if (sa.isAnnouncing("Multikicker")) {
|
||||
ManaCost mkCost = sa.getMultiKickerManaCost();
|
||||
ManaCost mCost = sa.getPayCosts().getTotalMana();
|
||||
boolean isZeroCost = mCost.isZero();
|
||||
|
||||
@@ -13,23 +13,17 @@ public class BranchEffect extends SpellAbilityEffect {
|
||||
|
||||
// TODO Reuse SpellAbilityCondition and areMet() here instead of repeating each
|
||||
|
||||
int value = 0;
|
||||
if (sa.hasParam("BranchCondition")) {
|
||||
if (sa.getParam("BranchCondition").equals("ChosenCard")) {
|
||||
value = host.getChosenCards().size();
|
||||
}
|
||||
} else {
|
||||
value = AbilityUtils.calculateAmount(host, sa.getParam("BranchConditionSVar"), sa);
|
||||
}
|
||||
String branchSVar = sa.getParam("BranchConditionSVar");
|
||||
String branchCompare = sa.getParamOrDefault("BranchConditionSVarCompare", "GE1");
|
||||
|
||||
String operator = branchCompare.substring(0, 2);
|
||||
String operand = branchCompare.substring(2);
|
||||
|
||||
final int svarValue = AbilityUtils.calculateAmount(host, branchSVar, sa);
|
||||
final int operandValue = AbilityUtils.calculateAmount(host, operand, sa);
|
||||
|
||||
SpellAbility sub = null;
|
||||
if (Expressions.compare(value, operator, operandValue)) {
|
||||
if (Expressions.compare(svarValue, operator, operandValue)) {
|
||||
sub = sa.getAdditionalAbility("TrueSubAbility");
|
||||
} else {
|
||||
sub = sa.getAdditionalAbility("FalseSubAbility");
|
||||
|
||||
@@ -35,8 +35,11 @@ public class TapOrUntapEffect extends SpellAbilityEffect {
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
Player activator = sa.getActivatingPlayer();
|
||||
PlayerController pc = activator.getController();
|
||||
Player tapper = sa.getActivatingPlayer();
|
||||
if (sa.hasParam("Tapper")) {
|
||||
tapper = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Tapper"), sa).getFirst();
|
||||
}
|
||||
PlayerController pc = tapper.getController();
|
||||
|
||||
CardCollection tapped = new CardCollection();
|
||||
final Map<Player, CardCollection> untapMap = Maps.newHashMap();
|
||||
@@ -50,12 +53,8 @@ public class TapOrUntapEffect extends SpellAbilityEffect {
|
||||
|
||||
// If the effected card is controlled by the same controller of the SA, default to untap.
|
||||
boolean tap = pc.chooseBinary(sa, Localizer.getInstance().getMessage("lblTapOrUntapTarget", CardTranslation.getTranslatedName(tgtC.getName())), PlayerController.BinaryChoiceType.TapOrUntap,
|
||||
!tgtC.getController().equals(activator) );
|
||||
!tgtC.getController().equals(tapper) );
|
||||
|
||||
Player tapper = activator;
|
||||
if (sa.hasParam("Tapper")) {
|
||||
tapper = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Tapper"), sa).getFirst();
|
||||
}
|
||||
if (tap) {
|
||||
if (tgtC.tap(true, sa, tapper)) tapped.add(tgtC);
|
||||
} else if (tgtC.untap(true)) {
|
||||
@@ -65,12 +64,12 @@ public class TapOrUntapEffect extends SpellAbilityEffect {
|
||||
if (!untapMap.isEmpty()) {
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Map, untapMap);
|
||||
activator.getGame().getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
|
||||
tapper.getGame().getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false);
|
||||
}
|
||||
if (!tapped.isEmpty()) {
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Cards, tapped);
|
||||
activator.getGame().getTriggerHandler().runTrigger(TriggerType.TapAll, runParams, false);
|
||||
tapper.getGame().getTriggerHandler().runTrigger(TriggerType.TapAll, runParams, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2290,12 +2290,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
? ", or " : n + 2 == costs.length ? " or " : ", ");
|
||||
}
|
||||
} else if (keyword.startsWith("Multikicker")) {
|
||||
if (!keyword.endsWith("Generic")) {
|
||||
final String[] n = keyword.split(":");
|
||||
final Cost cost = new Cost(n[1], false);
|
||||
sbLong.append("Multikicker ").append(cost.toSimpleString());
|
||||
sbLong.append(" (").append(inst.getReminderText()).append(")").append("\r\n");
|
||||
}
|
||||
final String[] n = keyword.split(":");
|
||||
final Cost cost = new Cost(n[1], false);
|
||||
sbLong.append("Multikicker ").append(cost.toSimpleString());
|
||||
sbLong.append(" (").append(inst.getReminderText()).append(")").append("\r\n");
|
||||
} else if (keyword.startsWith("Kicker")) {
|
||||
sbLong.append(kickerDesc(keyword, inst.getReminderText())).append("\r\n");
|
||||
} else if (keyword.startsWith("Trample:")) {
|
||||
@@ -2583,41 +2581,34 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
final Cost cost = new Cost(n[1], false);
|
||||
final String costStr = cost.toSimpleString();
|
||||
final boolean manaOnly = cost.isOnlyManaCost();
|
||||
if (!keyword.endsWith("Generic")) {
|
||||
sbx.append("Kicker").append(manaOnly ? " " + costStr : "—" + costStr + ".");
|
||||
if (Lists.newArrayList(n).size() > 2) {
|
||||
sbx.append(" and/or ");
|
||||
final Cost cost2 = new Cost(n[2], false);
|
||||
sbx.append(cost2.toSimpleString());
|
||||
}
|
||||
if (!manaOnly) {
|
||||
if (cost.hasNoManaCost()) {
|
||||
remText = remText.replaceFirst(" pay an additional", "");
|
||||
remText = remText.replace(remText.charAt(8), Character.toLowerCase(remText.charAt(8)));
|
||||
} else {
|
||||
remText = remText.replaceFirst(" an additional", "");
|
||||
char c = remText.charAt(remText.indexOf(",") + 2);
|
||||
remText = remText.replace(c, Character.toLowerCase(c));
|
||||
remText = remText.replaceFirst(", ", " and ");
|
||||
}
|
||||
remText = remText.replaceFirst("as", "in addition to any other costs as");
|
||||
if (remText.contains(" tap ")) {
|
||||
if (remText.contains("tap a")) {
|
||||
String noun = remText.substring(remText.indexOf("untapped") + 9, remText.indexOf(" in "));
|
||||
remText = remText.replace(remText.substring(12, remText.indexOf(" in ")),
|
||||
Lang.nounWithNumeralExceptOne(1, noun) + " ");
|
||||
} else {
|
||||
remText = remText.replaceFirst(" untapped ", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
sbx.append(" (").append(remText).append(")\r\n");
|
||||
} else {
|
||||
sbx.append("As an additional cost to cast this spell, you may ");
|
||||
String costS = StringUtils.uncapitalize(costStr);
|
||||
sbx.append(cost.hasManaCost() ? "pay " + costS : costS);
|
||||
sbx.append(".").append("\r\n");
|
||||
sbx.append("Kicker").append(manaOnly ? " " + costStr : "—" + costStr + ".");
|
||||
if (Lists.newArrayList(n).size() > 2) {
|
||||
sbx.append(" and/or ");
|
||||
final Cost cost2 = new Cost(n[2], false);
|
||||
sbx.append(cost2.toSimpleString());
|
||||
}
|
||||
if (!manaOnly) {
|
||||
if (cost.hasNoManaCost()) {
|
||||
remText = remText.replaceFirst(" pay an additional", "");
|
||||
remText = remText.replace(remText.charAt(8), Character.toLowerCase(remText.charAt(8)));
|
||||
} else {
|
||||
remText = remText.replaceFirst(" an additional", "");
|
||||
char c = remText.charAt(remText.indexOf(",") + 2);
|
||||
remText = remText.replace(c, Character.toLowerCase(c));
|
||||
remText = remText.replaceFirst(", ", " and ");
|
||||
}
|
||||
remText = remText.replaceFirst("as", "in addition to any other costs as");
|
||||
if (remText.contains(" tap ")) {
|
||||
if (remText.contains("tap a")) {
|
||||
String noun = remText.substring(remText.indexOf("untapped") + 9, remText.indexOf(" in "));
|
||||
remText = remText.replace(remText.substring(12, remText.indexOf(" in ")),
|
||||
Lang.nounWithNumeralExceptOne(1, noun) + " ");
|
||||
} else {
|
||||
remText = remText.replaceFirst(" untapped ", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
sbx.append(" (").append(remText).append(")\r\n");
|
||||
return sbx.toString();
|
||||
}
|
||||
|
||||
@@ -3028,11 +3019,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
sbBefore.append(sbCost).append(" (").append(inst.getReminderText()).append(")");
|
||||
sbBefore.append("\r\n");
|
||||
} else if (keyword.startsWith("Multikicker")) {
|
||||
if (!keyword.endsWith("Generic")) {
|
||||
final String[] n = keyword.split(":");
|
||||
final Cost cost = new Cost(n[1], false);
|
||||
sbBefore.append("Multikicker ").append(cost.toSimpleString()).append(" (").append(inst.getReminderText()).append(")").append("\r\n");
|
||||
}
|
||||
final String[] n = keyword.split(":");
|
||||
final Cost cost = new Cost(n[1], false);
|
||||
sbBefore.append("Multikicker ").append(cost.toSimpleString()).append(" (").append(inst.getReminderText()).append(")").append("\r\n");
|
||||
} else if (keyword.startsWith("Kicker")) {
|
||||
sbBefore.append(kickerDesc(keyword, inst.getReminderText())).append("\r\n");
|
||||
} else if (keyword.startsWith("AlternateAdditionalCost")) {
|
||||
@@ -4622,7 +4611,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
|
||||
private int multiKickerMagnitude = 0;
|
||||
public final void addMultiKickerMagnitude(final int n) { multiKickerMagnitude += n; }
|
||||
public final void setKickerMagnitude(final int n) { multiKickerMagnitude = n; }
|
||||
public final int getKickerMagnitude() {
|
||||
if (multiKickerMagnitude > 0) {
|
||||
@@ -4673,7 +4661,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
public final boolean isUntapped() {
|
||||
return !tapped;
|
||||
}
|
||||
|
||||
public final boolean isTapped() {
|
||||
return tapped;
|
||||
}
|
||||
|
||||
@@ -74,9 +74,6 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the original cost and the face down info for a later check since the LKI copy will overwrite them
|
||||
ManaCost origCost = card.getState(card.isFaceDown() ? CardStateName.Original : card.getCurrentStateName()).getManaCost();
|
||||
|
||||
Player activator = this.getActivatingPlayer();
|
||||
if (activator == null) {
|
||||
activator = card.getController();
|
||||
@@ -90,6 +87,9 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the original cost and the face down info for a later check since the LKI copy will overwrite them
|
||||
ManaCost origCost = card.getState(card.isFaceDown() ? CardStateName.Original : card.getCurrentStateName()).getManaCost();
|
||||
|
||||
// do performanceMode only for cases where the activator is different than controller
|
||||
if (!Spell.performanceMode && !card.getController().equals(activator)) {
|
||||
// always make a lki copy in this case?
|
||||
@@ -105,10 +105,8 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
|
||||
|
||||
// for uncastables like lotus bloom, check if manaCost is blank (except for morph spells)
|
||||
// but ignore if it comes from PlayEffect
|
||||
if (!isCastFaceDown()
|
||||
&& !isCastFromPlayEffect()
|
||||
&& isBasicSpell()
|
||||
&& origCost.isNoCost()) {
|
||||
if (!isCastFaceDown() && !isCastFromPlayEffect()
|
||||
&& isBasicSpell() && origCost.isNoCost()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -117,7 +115,7 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
|
||||
}
|
||||
|
||||
return true;
|
||||
} // canPlay()
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
|
||||
@@ -753,10 +753,8 @@ public final class StaticAbilityContinuous {
|
||||
Iterables.removeIf(newKeywords, new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
if (input.contains("CardManaCost")) {
|
||||
if (affectedCard.getManaCost().isNoCost()) {
|
||||
return true;
|
||||
}
|
||||
if (input.contains("CardManaCost") && affectedCard.getManaCost().isNoCost()) {
|
||||
return true;
|
||||
}
|
||||
// replace one Keyword with list of keywords
|
||||
if (input.startsWith("Protection") && input.contains("CardColors")) {
|
||||
@@ -897,7 +895,7 @@ public final class StaticAbilityContinuous {
|
||||
}
|
||||
}
|
||||
|
||||
if (!addedAbilities.isEmpty() || addReplacements != null || addTriggers != null || addStatics != null
|
||||
if (!addedAbilities.isEmpty() || !addedTrigger.isEmpty() || addReplacements != null || addStatics != null
|
||||
|| removeAllAbilities) {
|
||||
affectedCard.addChangedCardTraits(
|
||||
addedAbilities, null, addedTrigger, addedReplacementEffects, addedStaticAbility, removeAllAbilities, removeNonMana,
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:3 B
|
||||
Types:Sorcery
|
||||
A:SP$ RevealHand | ValidTgts$ Opponent | RememberRevealed$ True | SubAbility$ DBChoose | SpellDescription$ Target opponent reveals their hand.
|
||||
SVar:DBChoose:DB$ ChooseCard | ChoiceZone$ Hand | Amount$ 1 | Choices$ Card.nonLand+IsRemembered | ChoiceDesc$ nonland | FromDesc$ it | SubAbility$ DBBranch | ChoiceTitle$ You may choose a nonland card | SpellDescription$ You may choose a nonland card from it.
|
||||
SVar:DBBranch:DB$ Branch | BranchCondition$ ChosenCard | TrueSubAbility$ DBDiscard | FalseSubAbility$ DBDiscard2 | StackDescription$ If they do, {p:Targeted} discards that card. If they don't, {p:Targeted} discards two cards. | SpellDescription$ If you do, that player discards that card. If you don't, that player discards two cards.
|
||||
SVar:DBBranch:DB$ Branch | BranchConditionSVar$ Count$ChosenSize | TrueSubAbility$ DBDiscard | FalseSubAbility$ DBDiscard2 | StackDescription$ If they do, {p:Targeted} discards that card. If they don't, {p:Targeted} discards two cards. | SpellDescription$ If you do, that player discards that card. If you don't, that player discards two cards.
|
||||
SVar:DBDiscard:DB$ Discard | DefinedCards$ ChosenCard | Defined$ Targeted | Mode$ Defined | SubAbility$ DBCleanup
|
||||
SVar:DBDiscard2:DB$ Discard | Defined$ Targeted | NumCards$ 2 | Mode$ TgtChoose | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearChosenCard$ True
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:2 B
|
||||
Types:Sorcery
|
||||
A:SP$ RevealHand | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | RememberRevealed$ True | SubAbility$ DBChoose | SpellDescription$ Target opponent reveals their hand.
|
||||
SVar:DBChoose:DB$ ChooseCard | ChoiceZone$ Hand | Amount$ 1 | Choices$ Card.nonLand+IsRemembered | ChoiceDesc$ nonland | FromDesc$ it | SubAbility$ DBBranch | ChoiceTitle$ You may choose a nonland card | SpellDescription$ You may choose a nonland card from it.
|
||||
SVar:DBBranch:DB$ Branch | BranchCondition$ ChosenCard | TrueSubAbility$ DBDiscard | FalseSubAbility$ DBPutCounter | StackDescription$ If they do, {p:Targeted} discards that card. If they don't, they put two +1/+1 counters on a creature or Vehicle they control. | SpellDescription$ If you do, that player discards that card. If you don't, put two +1/+1 counters on a creature or Vehicle you control.
|
||||
SVar:DBBranch:DB$ Branch | BranchConditionSVar$ Count$ChosenSize | TrueSubAbility$ DBDiscard | FalseSubAbility$ DBPutCounter | StackDescription$ If they do, {p:Targeted} discards that card. If they don't, they put two +1/+1 counters on a creature or Vehicle they control. | SpellDescription$ If you do, that player discards that card. If you don't, put two +1/+1 counters on a creature or Vehicle you control.
|
||||
SVar:DBDiscard:DB$ Discard | DefinedCards$ ChosenCard | Defined$ Targeted | Mode$ Defined | SubAbility$ DBCleanup
|
||||
SVar:DBPutCounter:DB$ PutCounter | Choices$ Creature.YouCtrl,Vehicle.YouCtrl | ChoiceTitle$ Choose a creature or Vehicle you control | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearChosenCard$ True
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:U B
|
||||
Types:Instant
|
||||
A:SP$ Dig | ValidTgts$ Opponent | DigNum$ 2 | ChangeNum$ 1 | DestinationZone$ Exile | DestinationZone2$ Library | ExileFaceDown$ True | ChangeValid$ Card | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Look at the top two cards of target opponent's library. Exile one of them face down and put the other on the bottom of that library. You may look at and play the exiled card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell.
|
||||
SVar:DBEffect:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ STPlay | Duration$ Permanent | ForgetOnMoved$ Exile | SubAbility$ DBCleanup | StackDescription$ Exile one of them face down and put the other on the bottom of that library. You may look at and play the exiled card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell.
|
||||
SVar:STPlay:Mode$ Continuous | MayLookAt$ You | MayPlay$ True | MayPlayIgnoreType$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Secondary$ True | Description$ You may look at and play the exiled card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell.
|
||||
SVar:STPlay:Mode$ Continuous | MayLookAt$ You | MayPlay$ True | MayPlayIgnoreColor$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Secondary$ True | Description$ You may look at and play the exiled card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
K:Flashback:1 U B
|
||||
DeckHas:Ability$Graveyard
|
||||
|
||||
@@ -385,6 +385,7 @@ Guff
|
||||
Huatli
|
||||
Inzerva
|
||||
Jace
|
||||
Jared
|
||||
Jaya
|
||||
Jeska
|
||||
Kaito
|
||||
|
||||
Reference in New Issue
Block a user