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 1df1ea84117..e28a56cd997 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1231,13 +1231,15 @@ public class Card extends GameEntity implements Comparable { // Run triggers int curCounters = oldValue == null ? 0 : oldValue; + final Map runParams = Maps.newTreeMap(); + runParams.put("Card", this); + runParams.put("CounterType", counterName); for (int i = 0; i < delta && curCounters != 0; i++) { - final Map runParams = Maps.newTreeMap(); - runParams.put("Card", this); - runParams.put("CounterType", counterName); runParams.put("NewCounterAmount", --curCounters); getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams, false); } + runParams.put("CounterAmount", delta); + getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemovedOnce, runParams, false); } @Override diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemoved.java b/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemoved.java index c58ad177741..46e0bc5fa41 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemoved.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemoved.java @@ -54,22 +54,22 @@ public class TriggerCounterRemoved extends Trigger { final CounterType addedType = (CounterType) runParams2.get("CounterType"); final Integer addedNewCounterAmount = (Integer) runParams2.get("NewCounterAmount"); - if (this.mapParams.containsKey("ValidCard")) { - if (!addedTo.isValid(this.mapParams.get("ValidCard").split(","), this.getHostCard().getController(), + if (hasParam("ValidCard")) { + if (!addedTo.isValid(getParam("ValidCard").split(","), this.getHostCard().getController(), this.getHostCard(), null)) { return false; } } - if (this.mapParams.containsKey("CounterType")) { - final String type = this.mapParams.get("CounterType"); + if (hasParam("CounterType")) { + final String type = getParam("CounterType"); if (!type.equals(addedType.toString())) { return false; } } - if (this.mapParams.containsKey("NewCounterAmount")) { - final String amtString = this.mapParams.get("NewCounterAmount"); + if (hasParam("NewCounterAmount")) { + final String amtString = getParam("NewCounterAmount"); int amt = Integer.parseInt(amtString); if(amt != addedNewCounterAmount.intValue()) { return false; diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemovedOnce.java b/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemovedOnce.java new file mode 100644 index 00000000000..4e02b6d8df4 --- /dev/null +++ b/forge-game/src/main/java/forge/game/trigger/TriggerCounterRemovedOnce.java @@ -0,0 +1,87 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.game.trigger; + +import forge.game.card.Card; +import forge.game.card.CounterType; +import forge.game.spellability.SpellAbility; + +/** + *

+ * Trigger_CounterRemovedOnce class. + *

+ * + * @author Forge + * @version $Id: TriggerCounterRemovedOnce.java 12297 2011-11-28 19:56:47Z jendave $ + */ +public class TriggerCounterRemovedOnce extends Trigger { + + /** + *

+ * Constructor for Trigger_CounterRemovedOnce. + *

+ * + * @param params + * a {@link java.util.HashMap} object. + * @param host + * a {@link forge.game.card.Card} object. + * @param intrinsic + * the intrinsic + */ + public TriggerCounterRemovedOnce(final java.util.Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /** {@inheritDoc} */ + @Override + public final boolean performTest(final java.util.Map runParams2) { + final Card removedFrom = (Card) runParams2.get("Card"); + final CounterType removedType = (CounterType) runParams2.get("CounterType"); + + if (hasParam("ValidCard")) { + if (!removedFrom.isValid(getParam("ValidCard").split(","), this.getHostCard().getController(), + this.getHostCard(), null)) { + return false; + } + } + + if (hasParam("CounterType")) { + final String type = getParam("CounterType"); + if (!type.equals(removedType.toString())) { + return false; + } + } + + return true; + } + + /** {@inheritDoc} */ + @Override + public final void setTriggeringObjects(final SpellAbility sa) { + sa.setTriggeringObject("Card", this.getRunParams().get("Card")); + sa.setTriggeringObject("Amount", this.getRunParams().get("CounterAmount")); + } + + @Override + public String getImportantStackObjects(SpellAbility sa) { + StringBuilder sb = new StringBuilder(); + sb.append("Removed from: ").append(sa.getTriggeringObject("Card")); + sb.append(" Amount: ").append(sa.getTriggeringObject("Amount")); + return sb.toString(); + } +} diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerCrewed.java b/forge-game/src/main/java/forge/game/trigger/TriggerCrewed.java index 0f71c4937ad..e784432b422 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerCrewed.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerCrewed.java @@ -14,20 +14,20 @@ public class TriggerCrewed extends Trigger { @Override public boolean performTest(Map runParams2) { - if (this.mapParams.containsKey("ValidVehicle")) { - if (!matchesValid(runParams2.get("Vehicle"), this.mapParams.get("ValidVehicle").split(","), + if (hasParam("ValidVehicle")) { + if (!matchesValid(runParams2.get("Vehicle"), getParam("ValidVehicle").split(","), this.getHostCard())) { return false; } } - if (this.mapParams.containsKey("ValidCrew")) { + if (hasParam("ValidCrew")) { if (runParams2.get("Crew") == null) { return false; } boolean passes = false; for (Object member : (CardCollection)runParams2.get("Crew")) { - passes |= matchesValid(member, this.mapParams.get("ValidCrew").split(","), + passes |= matchesValid(member, getParam("ValidCrew").split(","), this.getHostCard()); } if (!passes) diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java index 00e568f24e1..27456ad5579 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java @@ -38,6 +38,7 @@ public enum TriggerType { CounterAddedOnce(TriggerCounterAddedOnce.class), Countered(TriggerCountered.class), CounterRemoved(TriggerCounterRemoved.class), + CounterRemovedOnce(TriggerCounterRemovedOnce.class), Crewed(TriggerCrewed.class), Cycled(TriggerCycled.class), DamageDealtOnce(TriggerDamageDealtOnce.class), diff --git a/forge-gui/res/cardsfolder/a/accursed_witch_infectious_curse.txt b/forge-gui/res/cardsfolder/a/accursed_witch_infectious_curse.txt index 0e03dc209fd..8cd5ebdeb69 100644 --- a/forge-gui/res/cardsfolder/a/accursed_witch_infectious_curse.txt +++ b/forge-gui/res/cardsfolder/a/accursed_witch_infectious_curse.txt @@ -3,7 +3,7 @@ ManaCost:3 B Types:Creature Human Shaman PT:4/2 S:Mode$ ReduceCost | ValidTarget$ Card.Self | Activator$ Player.Opponent | Type$ Spell | Amount$ 1 | Description$ Spells your opponents cast that target CARDNAME cost {1} less to cast. -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigChoose | TriggerDescription$ When CARDNAME dies, return it to the battlefield transformed under your control attached to target opponent. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigChoose | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, return it to the battlefield transformed under your control attached to target opponent. SVar:TrigChoose:DB$ Pump | ValidTgts$ Opponent | TgtPrompt$ Choose a opponent | IsCurse$ True | SubAbility$ DBChange SVar:DBChange:DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | AttachedToPlayer$ ParentTarget | Transformed$ True | GainControl$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/accursed_witch.jpg diff --git a/forge-gui/res/cardsfolder/a/angel_of_fury.txt b/forge-gui/res/cardsfolder/a/angel_of_fury.txt index 67c592fe4b6..99d991293bc 100644 --- a/forge-gui/res/cardsfolder/a/angel_of_fury.txt +++ b/forge-gui/res/cardsfolder/a/angel_of_fury.txt @@ -3,7 +3,7 @@ ManaCost:4 W W Types:Creature Angel PT:3/5 K:Flying -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | OptionalDecider$ You | ValidCard$ Card.Self | Execute$ TrigChange | TriggerDescription$ When CARDNAME dies, you may shuffle it into its owner's library. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | OptionalDecider$ You | ValidCard$ Card.Self | Execute$ TrigChange | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may shuffle it into its owner's library. SVar:TrigChange:DB$ChangeZone | Origin$ Graveyard | Destination$ Library | Shuffle$ True | Defined$ TriggeredCard SVar:Picture:http://www.wizards.com/global/images/magic/general/angel_of_fury.jpg Oracle:Flying\nWhen Angel of Fury dies, you may shuffle it into its owner's library. diff --git a/forge-gui/res/cardsfolder/upcoming/angraths_rampage.txt b/forge-gui/res/cardsfolder/upcoming/angraths_rampage.txt new file mode 100644 index 00000000000..7560309aa52 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/angraths_rampage.txt @@ -0,0 +1,8 @@ +Name:Angrath's Rampage +ManaCost:B R +Types:Sorcery +A:SP$ Charm | Cost$ B R | Choices$ SacArtifact,SacCreature,SacPW +SVar:SacArtifact:DB$ Sacrifice | ValidTgts$ Player | SacValid$ Artifact | Amount$ 1 | SpellDescription$ Target player sacrifices an artifact. +SVar:SacCreature:DB$ Sacrifice | ValidTgts$ Player | SacValid$ Creature | Amount$ 1 | SpellDescription$ Target player sacrifices an creature. +SVar:SacPW:DB$ Sacrifice | ValidTgts$ Player | SacValid$ Planeswalker | Amount$ 1 | SpellDescription$ Target player sacrifices an planeswalker. +Oracle:Choose one —\n• Target player sacrifices an artifact.\n• Target player sacrifices a creature.\n• Target player sacrifices a planeswalker. diff --git a/forge-gui/res/cardsfolder/upcoming/arlinn_voice_of_the_pack.txt b/forge-gui/res/cardsfolder/upcoming/arlinn_voice_of_the_pack.txt new file mode 100644 index 00000000000..df2f70dcac0 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/arlinn_voice_of_the_pack.txt @@ -0,0 +1,10 @@ +Name:Arlinn, Voice of the Pack +ManaCost:4 G G +Types:Legendary Planeswalker Arlinn +Loyalty:7 +K:ETBReplacement:Other:AddExtraCounter:Mandatory:Battlefield:Creature.Wolf+YouCtrl,Creature.Werewolf+YouCtrl +SVar:AddExtraCounter:DB$ PutCounter | ETB$ True | Defined$ ReplacedCard | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$Each creature you control that's a Wolf or Werewolf enters the battlefield with an additional +1/+1 counter on it. +SVar:PlayMain1:TRUE +DeckHints:Type$Wolf & Type$Werewolf +A:AB$ Token | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ g_2_2_wolf | TokenOwner$ You | LegacyImage$ g 2 2 wolf war | SpellDescription$ Create a 2/2 green Wolf creature token. +Oracle:Each creature you control that's a Wolf or Werewolf enters the battlefield with an additional +1/+1 counter on it.\n[-2]: Create a 2/2 green Wolf creature token. diff --git a/forge-gui/res/cardsfolder/upcoming/chandra_fire_artisan.txt b/forge-gui/res/cardsfolder/upcoming/chandra_fire_artisan.txt new file mode 100644 index 00000000000..8693d00ae30 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/chandra_fire_artisan.txt @@ -0,0 +1,13 @@ +Name:Chandra, Fire Artisan +ManaCost:2 R R +Types:Legendary Planeswalker Chandra +Loyalty:4 +T:Mode$ CounterRemovedOnce | ValidCard$ Card.Self | CounterType$ LOYALTY | TriggerZones$ Battlefield | Execute$ TrigDmg | TriggerDescription$ Whenever one or more loyalty counters are removed from CARDNAME, CARDNAME deals that much damage to target opponent or planeswalker. +SVar:TrigDmg:DB$ DealDamage | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ X | References$ X +SVar:X:TriggerCount$Amount +A:AB$ Mill | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Defined$ You | NumCards$ 1 | Destination$ Exile | RememberMilled$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top card of your library. You may play it this turn. +SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | RememberObjects$ Remembered | ForgetOnMoved$ Exile | SubAbility$ DBCleanup +SVar:STPlay:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Exile | Affected$ Card.IsRemembered | MayPlay$ True | Description$ You may play the card(s) this turn. +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ Mill | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Defined$ You | NumCards$ 7 | Destination$ Exile | RememberMilled$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top seven cards of your library. You may play them this turn. +Oracle:Whenever one or more loyalty counters are removed from Chandra, Fire Artisan, she deals that much damage to target opponent or planeswalker.\n[+1]: Exile the top card of your library. You may play it this turn.\n[-7]: Exile the top seven cards of your library. You may play them this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/dovin_hand_of_control.txt b/forge-gui/res/cardsfolder/upcoming/dovin_hand_of_control.txt new file mode 100644 index 00000000000..dc78bf9a1db --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/dovin_hand_of_control.txt @@ -0,0 +1,8 @@ +Name:Dovin, Hand of Control +ManaCost:2 W/U +Types:Legendary Planeswalker Dovin +Loyalty:5 +S:Mode$ RaiseCost | ValidCard$ Artifact,Instant,Sorcery | Activator$ Opponent | Type$ Spell | Amount$ 1 | Description$ Artifact, instant, and sorcery spells your opponents cast cost {1} more to cast. +A:AB$ Pump | Cost$ SubCounter<1/LOYALTY> | ValidTgts$ Permanent.OppCtrl | TgtPrompt$ Select target permanent an opponent controls | Planeswalker$ True | KW$ Prevent all damage that would be dealt to and dealt by CARDNAME. | IsCurse$ True | UntilYourNextTurn$ True | SpellDescription$ Until your next turn, prevent all damage that would be dealt to and dealt by target permanent an opponent controls. +AI:RemoveDeck:All +Oracle:Artifact, instant, and sorcery spells your opponents cast cost {1} more to cast.\n[-1]: Until your next turn, prevent all damage that would be dealt to and dealt by target permanent an opponent controls. diff --git a/forge-gui/res/cardsfolder/upcoming/heartfire.txt b/forge-gui/res/cardsfolder/upcoming/heartfire.txt new file mode 100644 index 00000000000..f4c649d22c0 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/heartfire.txt @@ -0,0 +1,6 @@ +Name:Heartfire +ManaCost:1 R +Types:Instant +A:SP$ DealDamage | Cost$ 1 R Sac<1/Creature;Planeswalker/creature or planeswalker> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 4 | SpellDescription$ CARDNAME deals 4 damage to any target. +SVar:AIPreference:SacCost$Creature.token,Planeswalker.cmcLE2 +Oracle:As an additional cost to cast this spell, sacrifice a creature or planeswalker.\nHeartfire deals 4 damage to any target. diff --git a/forge-gui/res/cardsfolder/upcoming/jiang_yanggu_wildcrafter.txt b/forge-gui/res/cardsfolder/upcoming/jiang_yanggu_wildcrafter.txt new file mode 100644 index 00000000000..a010234816c --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/jiang_yanggu_wildcrafter.txt @@ -0,0 +1,9 @@ +Name:Jiang Yanggu, Wildcrafter +ManaCost:2 G +Types:Legendary Planeswalker Yanggu +Loyalty:3 +S:Mode$ Continuous | Affected$ Creature.YouCtrl+counters_GE1_P1P1 | AddAbility$ AnyMana | Description$ Each creature you control with a +1/+1 counter on it has "{T}: Add one mana of any color." +SVar:AnyMana:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color. +DeckHints:Ability$Counters +A:AB$ PutCounter | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on target creature. +Oracle:Each creature you control with a +1/+1 counter on it has "{T}: Add one mana of any color."\n[-1]: Put a +1/+1 counter on target creature. diff --git a/forge-gui/res/cardsfolder/upcoming/nahiri_storm_of_stone.txt b/forge-gui/res/cardsfolder/upcoming/nahiri_storm_of_stone.txt index c9d769a8bc5..0a0b4508e01 100644 --- a/forge-gui/res/cardsfolder/upcoming/nahiri_storm_of_stone.txt +++ b/forge-gui/res/cardsfolder/upcoming/nahiri_storm_of_stone.txt @@ -3,6 +3,7 @@ ManaCost:2 R/W R/W Types:Legendary Planeswalker Nahiri Loyalty:6 S:Mode$ Continuous | Affected$ Creature.YouCtrl | EffectZone$ Battlefield | AddKeyword$ First Strike | Condition$ PlayerTurn | Description$ As long as it's your turn, creatures you control have first strike and equip abilities you activate cost {1} less to activate. -A:AB$ DealDamage | Cost$ SubCounter | ValidTgts$ Creature.tapped | TgtPrompt$ Select target tapped creature | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to target tapped creature. +S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Activated.Equip | Activator$ You | Amount$ 1 | Condition$ PlayerTurn | Secondary$ True | Description$ Equip abilities you activate cost {1} less to activate. +A:AB$ DealDamage | Cost$ SubCounter | Planeswalker$ True | ValidTgts$ Creature.tapped | TgtPrompt$ Select target tapped creature | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals X damage to target tapped creature. SVar:X:Count$xPaid Oracle:As long as it's your turn, creatures you control have first strike and equip abilities you activate cost {1} less to activate.\n-X: Nahiri, Storm of Stone deals X damage to target tapped creature. diff --git a/forge-gui/res/cardsfolder/upcoming/roalesk_apex_hybrid.txt b/forge-gui/res/cardsfolder/upcoming/roalesk_apex_hybrid.txt index 23de8f1671f..cc3cf8bb579 100644 --- a/forge-gui/res/cardsfolder/upcoming/roalesk_apex_hybrid.txt +++ b/forge-gui/res/cardsfolder/upcoming/roalesk_apex_hybrid.txt @@ -6,7 +6,7 @@ K:Flying K:Trample T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPutCounter | TriggerDescription$ When CARDNAME enters the battlefield, put two +1/+1 counters on another target creature you control. SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.Other+YouCtrl | TgtPrompt$ Select another target creature you control | CounterType$ P1P1 | CounterNum$ 2 -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigProliferate | TriggerDescription$ When CARDNAME dies, proliferate, then proliferate again. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | TriggerController$ TriggeredCardController | Execute$ TrigProliferate | TriggerDescription$ When CARDNAME dies, proliferate, then proliferate again. SVar:TrigProliferate:DB$ Proliferate | SubAbility$ TrigProliferate2 SVar:TrigProliferate2:DB$ Proliferate DeckHas:Ability$Proliferate diff --git a/forge-gui/res/cardsfolder/upcoming/the_elderspell.txt b/forge-gui/res/cardsfolder/upcoming/the_elderspell.txt new file mode 100644 index 00000000000..32045061fc5 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/the_elderspell.txt @@ -0,0 +1,10 @@ +Name:The Elderspell +ManaCost:B B +Types:Sorcery +A:SP$ Destroy | Cost$ B B | ValidTgts$ Planeswalker | TgtPrompt$ Select target planeswalker | TargetMin$ 0 | TargetMax$ MaxTargets | References$ MaxTargets | SubAbility$ DBChooseCard | RememberDestroyed$ True | SpellDescription$ Destroy any number of target planeswalkers. Choose a planeswalker you control. Put two loyalty counters on it for each planeswalker destroyed this way. +SVar:DBChooseCard:DB$ ChooseCard | Defined$ You | Amount$ 1 | Choices$ Planeswalker.YouCtrl | Mandatory$ True | SubAbility$ DBPutLoyalty +SVar:DBPutLoyalty:DB$ PutCounter | Defined$ ChosenCard | CounterType$ LOYALTY | CounterNum$ X | References$ X | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:MaxTargets:Count$Valid Planeswalker +SVar:X:Count$RememberedSize/Twice +Oracle:Destroy any number of target planeswalkers. Choose a planeswalker you control. Put two loyalty counters on it for each planeswalker destroyed this way.