From ae6c0200652ec7c9c330db8b9e4aea7308c28857 Mon Sep 17 00:00:00 2001 From: Northmoc <103371817+Northmoc@users.noreply.github.com> Date: Sat, 2 Mar 2024 08:44:11 -0500 Subject: [PATCH] Alchemy Incorporate (#4763) * Alchemy Incorporate * Tweaks for Volrath's Shapeshifter --- .../ability/effects/AnimateEffectBase.java | 49 +++++++++++++++---- .../src/main/java/forge/game/card/Card.java | 19 +++++-- .../main/java/forge/game/card/CardView.java | 6 ++- .../upcoming/guildpact_greenwalker.txt | 11 +++++ 4 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/guildpact_greenwalker.txt diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java index ee9dc0d1a83..e7f09c53919 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java @@ -31,6 +31,7 @@ import forge.card.ColorSet; import forge.card.RemoveType; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostParser; +import forge.game.cost.Cost; import forge.game.Game; import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; @@ -81,6 +82,28 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { source.addRemembered(c); } + // Alchemy "incorporate" cost + ColorSet incColors = null; + if (sa.hasParam("Incorporate")) { + final String incorporate = sa.getParam("Incorporate"); + + Map params = new HashMap<>(); + params.put("Incorporate", incorporate); + params.put("Timestamp", timestamp); + params.put("Category", "Incorporate"); + c.addPerpetual(params); + + final ManaCost incMCost = new ManaCost(new ManaCostParser(incorporate)); + incColors = ColorSet.fromMask(incMCost.getColorProfile()); + final ManaCost newCost = ManaCost.combine(c.getManaCost(), incMCost); + c.addChangedManaCost(newCost, timestamp, 0); + c.updateManaCostForView(); + + if (c.getFirstSpellAbility() != null) { + c.getFirstSpellAbility().getPayCosts().add(new Cost(incorporate, false)); + } + } + if (!addType.isEmpty() || !removeType.isEmpty() || addAllCreatureTypes || !remove.isEmpty()) { if (perpetual) { Map params = new HashMap<>(); @@ -129,15 +152,10 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { if (colors != null) { final boolean overwrite = sa.hasParam("OverwriteColors"); - if (perpetual) { - Map params = new HashMap<>(); - params.put("Colors", colors); - params.put("Overwrite", overwrite); - params.put("Timestamp", timestamp); - params.put("Category", "Colors"); - c.addPerpetual(params); - } - c.addColor(colors, !overwrite, timestamp, 0, false); + handleColors(c, colors, timestamp, overwrite, perpetual); + } + if (incColors != null) { + handleColors(c, incColors, timestamp, false, perpetual); } if (sa.hasParam("LeaveBattlefield")) { @@ -273,4 +291,17 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { c.removeHiddenExtrinsicKeywords(timestamp, 0); } + static void handleColors(final Card c, final ColorSet colors, final long timestamp, final boolean overwrite, + final boolean perpetual) { + if (perpetual) { + Map params = new HashMap<>(); + params.put("Colors", colors); + params.put("Overwrite", overwrite); + params.put("Timestamp", timestamp); + params.put("Category", "Colors"); + c.addPerpetual(params); + } + c.addColor(colors, !overwrite, timestamp, 0, false); + } + } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 59441ca82eb..135a79f1648 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -592,6 +592,10 @@ public class Card extends GameEntity implements Comparable, IHasSVars { //view.getCurrentState().updateAbilityText(this, getCurrentState()); } + public void updateManaCostForView() { + currentState.getView().updateManaCost(this); + } + public final void updatePowerToughnessForView() { view.updateCounters(this); } @@ -4451,15 +4455,14 @@ public class Card extends GameEntity implements Comparable, IHasSVars { private int intensity = 0; public final void addIntensity(final int n) { - intensity = intensity + n; + intensity += n; view.updateIntensity(this); } public final int getIntensity(boolean total) { if (total && hasKeyword(Keyword.STARTING_INTENSITY)) { return getKeywordMagnitude(Keyword.STARTING_INTENSITY) + intensity; - } else { - return intensity; } + return intensity; } public final void setIntensity(final int n) { intensity = n; } public final boolean hasIntensity() { @@ -4520,6 +4523,15 @@ public class Card extends GameEntity implements Comparable, IHasSVars { long timestamp = (long) p.get("Timestamp"); CardTraitChanges ctc = oldCard.getChangedCardTraits().get(timestamp, (long) 0).copy(this, false); addChangedCardTraits(ctc, timestamp, (long) 0); + } else if (p.get("Category").equals("Incorporate")) { + long ts = (long) p.get("Timestamp"); + final ManaCost cCMC = oldCard.changedCardManaCost.get(ts, (long) 0); + addChangedManaCost(cCMC, ts, (long) 0); + updateManaCostForView(); + + if (getFirstSpellAbility() != null) { + getFirstSpellAbility().getPayCosts().add(new Cost((String) p.get("Incorporate"), false)); + } } else executePerpetual(p); } } @@ -5191,6 +5203,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { getView().updateChangedColorWords(this); getView().updateChangedTypes(this); + updateManaCostForView(); currentState.getView().updateAbilityText(this, currentState); view.updateNonAbilityText(this); diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index e314daef197..0323c03208c 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -1007,7 +1007,8 @@ public class CardView extends GameEntityView { // update the color only while in Game if (c.getGame() != null) { - currentStateView.updateColors(currentState); + if (c.hasPerpetual()) currentStateView.updateColors(c); + else currentStateView.updateColors(currentState); currentStateView.updateHasChangeColors(!Iterables.isEmpty(c.getChangedCardColors())); } } else { @@ -1288,6 +1289,9 @@ public class CardView extends GameEntityView { void updateManaCost(CardState c) { set(TrackableProperty.ManaCost, c.getManaCost()); } + void updateManaCost(Card c) { + set(TrackableProperty.ManaCost, c.getManaCost()); + } public String getOracleText() { return get(TrackableProperty.OracleText); diff --git a/forge-gui/res/cardsfolder/upcoming/guildpact_greenwalker.txt b/forge-gui/res/cardsfolder/upcoming/guildpact_greenwalker.txt new file mode 100644 index 00000000000..c57bb9b007f --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/guildpact_greenwalker.txt @@ -0,0 +1,11 @@ +Name:Guildpact Greenwalker +ManaCost:2 G +Types:Creature Plant Rhino +PT:4/4 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChoose | TriggerDescription$ When CARDNAME enters the battlefield, you may choose a creature card in your hand. If you do, that card perpetually incorporates {1}{G} and gets +4/+4. +SVar:TrigChoose:DB$ ChooseCard | ChoiceZone$ Hand | Choices$ Creature.YouOwn | ChoiceTitle$ You may choose a creature card in your hand | SubAbility$ DBAnimate +SVar:DBAnimate:DB$ Animate | Defined$ ChosenCard | Incorporate$ 1 G | Duration$ Perpetual | SubAbility$ DBPump +SVar:DBPump:DB$ Pump | PumpZone$ Hand | Defined$ ChosenCard | Duration$ Perpetual | NumAtt$ 4 | NumDef$ 4 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True +S:Mode$ Continuous | Affected$ Creature.MultiColor+YouCtrl | AddKeyword$ Ward:2 | Description$ Multicolored creatures you control have ward {2}. +Oracle:When Guildpact Greenwalker enters the battlefield, you may choose a creature card in your hand. If you do, that card perpetually incorporates {1}{G} and gets +4/+4.\nMulticolored creatures you control have ward {2}.