From 1982f73e3dc02f165899ba726a5489189a27c59c Mon Sep 17 00:00:00 2001 From: Sol Date: Sun, 16 Feb 2014 17:15:44 +0000 Subject: [PATCH] - Added an Effect to gain Control of Spells. - Added Commandeer --- .gitattributes | 2 + .../main/java/forge/game/ability/ApiType.java | 1 + .../ability/effects/ChangeTargetsEffect.java | 5 +- .../ability/effects/ControlSpellEffect.java | 74 +++++++++++++++++++ .../SpellAbilityStackInstance.java | 17 +++-- forge-gui/res/cardsfolder/c/commandeer.txt | 9 +++ forge-gui/res/cardsfolder/m/muck_drubb.txt | 2 +- forge-gui/res/cardsfolder/s/spellskite.txt | 2 +- 8 files changed, 102 insertions(+), 10 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/ability/effects/ControlSpellEffect.java create mode 100644 forge-gui/res/cardsfolder/c/commandeer.txt diff --git a/.gitattributes b/.gitattributes index 3e132590774..7f281d7ceee 100644 --- a/.gitattributes +++ b/.gitattributes @@ -306,6 +306,7 @@ forge-game/src/main/java/forge/game/ability/effects/CloneEffect.java -text forge-game/src/main/java/forge/game/ability/effects/ControlExchangeEffect.java -text forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java -text forge-game/src/main/java/forge/game/ability/effects/ControlPlayerEffect.java -text +forge-game/src/main/java/forge/game/ability/effects/ControlSpellEffect.java -text forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java -text forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java -text forge-game/src/main/java/forge/game/ability/effects/CounterEffect.java -text @@ -2710,6 +2711,7 @@ forge-gui/res/cardsfolder/c/combust.txt svneol=native#text/plain forge-gui/res/cardsfolder/c/comet_storm.txt -text forge-gui/res/cardsfolder/c/command_of_unsummoning.txt svneol=native#text/plain forge-gui/res/cardsfolder/c/command_tower.txt -text +forge-gui/res/cardsfolder/c/commandeer.txt -text forge-gui/res/cardsfolder/c/commander_eesha.txt svneol=native#text/plain forge-gui/res/cardsfolder/c/commander_greven_il_vec.txt svneol=native#text/plain forge-gui/res/cardsfolder/c/commanders_authority.txt -text diff --git a/forge-game/src/main/java/forge/game/ability/ApiType.java b/forge-game/src/main/java/forge/game/ability/ApiType.java index ffa203bc15b..a7e7b2e7b93 100644 --- a/forge-game/src/main/java/forge/game/ability/ApiType.java +++ b/forge-game/src/main/java/forge/game/ability/ApiType.java @@ -38,6 +38,7 @@ public enum ApiType { Clone (CloneEffect.class), CopyPermanent (CopyPermanentEffect.class), CopySpellAbility (CopySpellAbilityEffect.class), + ControlSpell (ControlSpellEffect.class), ControlPlayer (ControlPlayerEffect.class), Counter (CounterEffect.class), DamageAll (DamageAllEffect.class), diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java index 3016d1df716..a433aa93d81 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeTargetsEffect.java @@ -45,6 +45,7 @@ public class ChangeTargetsEffect extends SpellAbilityEffect { Player chooser = sa.getActivatingPlayer(); // Redirect rules read 'you MAY choose new targets' ... okay! + // TODO: Don't even ask to change targets, if the SA and subs don't actually have targets boolean isOptional = sa.hasParam("Optional"); if( isOptional && !chooser.getController().confirmAction(sa, null, "Do you want to change targets of " + tgtSA.getHostCard() + "?")) continue; @@ -90,8 +91,8 @@ public class ChangeTargetsEffect extends SpellAbilityEffect { GameObject choice = Aggregates.random(candidates); changingTgtSA.getTargets().add(choice); changingTgtSI.updateTarget(changingTgtSA.getTargets()); - } else if (sa.hasParam("Defined")){ - GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa), null); + } else if (sa.hasParam("DefinedMagnet")){ + GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa, "DefinedMagnet"), null); if(changingTgtSA.canTarget(newTarget)) { changingTgtSA.resetTargets(); changingTgtSA.getTargets().add(newTarget); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ControlSpellEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ControlSpellEffect.java new file mode 100644 index 00000000000..481bc3f89d9 --- /dev/null +++ b/forge-game/src/main/java/forge/game/ability/effects/ControlSpellEffect.java @@ -0,0 +1,74 @@ +package forge.game.ability.effects; + +import forge.game.Game; +import forge.game.ability.SpellAbilityEffect; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityStackInstance; + +import java.util.List; + +public class ControlSpellEffect extends SpellAbilityEffect { + /* (non-Javadoc) + * @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility) + */ + @Override + protected String getStackDescription(SpellAbility sa) { + final StringBuilder sb = new StringBuilder(); + + List newController = getTargetPlayers(sa, "NewController"); + if (newController.isEmpty()) { + newController.add(sa.getActivatingPlayer()); + } + + sb.append(newController).append(" gains control of "); + + for(SpellAbility spell : getTargetSpells(sa)) { + Card c = spell.getHostCard(); + sb.append(" "); + if (c.isFaceDown()) { + sb.append("Morph"); + } else { + sb.append(c); + } + } + sb.append("."); + + return sb.toString(); + } + + + @Override + public void resolve(SpellAbility sa) { + // Gaining Control of Spells is a permanent effect + Card source = sa.getHostCard(); + + boolean exchange = sa.getParam("Mode").equals("Exchange"); + final List controllers = getDefinedPlayersOrTargeted(sa, "NewController"); + + final Player newController = controllers.isEmpty() ? sa.getActivatingPlayer() : controllers.get(0); + final Game game = newController.getGame(); + + List tgtSpells = getTargetSpells(sa); + + // If an Exchange needs to happen, make sure both parties are still in the right zones + + for(SpellAbility spell : tgtSpells) { + if (exchange) { + // Currently the only Exchange Control for Spells, is a Permanent Trigger + // Use "DefinedExchange" to Reference Object that is Exchanging the other direction + } + + Card tgtC = spell.getHostCard(); + if (!tgtC.equals(sa.getHostCard()) && !sa.getHostCard().getGainControlTargets().contains(tgtC)) { + sa.getHostCard().addGainControlTarget(tgtC); + } + + long tStamp = game.getNextTimestamp(); + tgtC.setController(newController, tStamp); + SpellAbilityStackInstance si = game.getStack().getInstanceFromSpellAbility(spell); + si.setActivator(newController); + } + } +} diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java index e035a9d647f..15a5ecf275e 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java @@ -42,19 +42,16 @@ public class SpellAbilityStackInstance { // gets cleared from the base SI // Coming off the Stack would work similarly, except it would just add the // full active SI instead of each of the parts - /** The ability. */ + private SpellAbility ability = null; - /** The sub instace. */ private SpellAbilityStackInstance subInstace = null; - private final Player activator; + private Player activator; // When going to a SubAbility that SA has a Instance Choice object - /** The tc. */ private TargetChoices tc = new TargetChoices(); private List splicedCards = null; - /** The stack description. */ private String stackDescription = null; // Adjusted Mana Cost @@ -297,7 +294,15 @@ public class SpellAbilityStackInstance { return true; } - + + public Player getActivator() { + return activator; + } + + public void setActivator(Player activator) { + this.activator = activator; + } + @Override public String toString() { return String.format("%s->%s", getSourceCard(), stackDescription); diff --git a/forge-gui/res/cardsfolder/c/commandeer.txt b/forge-gui/res/cardsfolder/c/commandeer.txt new file mode 100644 index 00000000000..b3ada9d903e --- /dev/null +++ b/forge-gui/res/cardsfolder/c/commandeer.txt @@ -0,0 +1,9 @@ +Name:Commandeer +ManaCost:5 U U +Types:Instant +A:SP$ ControlSpell | Cost$ 5 U U | ValidTgts$ Card.nonCreature | TgtZone$ Stack | Mode$ Gain | SubAbility$ DBChooseTargets | SpellDescription$ Gain control of target noncreature spell. You may choose new targets for it. (If that spell is an artifact, enchantment, or planeswalker, the permanent enters the battlefield under your control.) +SVar:DBChooseTargets:DB$ ChangeTargets | Defined$ Targeted | Optional$ True +SVar:AltCost:Cost$ ExileFromHand<2/Card.Blue> | Description$ You may exile two blue cards from your hand rather than pay CARDNAME's mana cost. +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/commandeer.jpg +Oracle:You may exile two blue cards from your hand rather than pay Commandeer's mana cost.\nGain control of target noncreature spell. You may choose new targets for it. (If that spell is an artifact, enchantment, or planeswalker, the permanent enters the battlefield under your control.) diff --git a/forge-gui/res/cardsfolder/m/muck_drubb.txt b/forge-gui/res/cardsfolder/m/muck_drubb.txt index c07a0f1ee5d..5a17706db2b 100644 --- a/forge-gui/res/cardsfolder/m/muck_drubb.txt +++ b/forge-gui/res/cardsfolder/m/muck_drubb.txt @@ -4,7 +4,7 @@ Types:Creature Beast PT:3/3 K:Flash T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | TriggerDescription$ When CARDNAME enters the battlefield, change the target of target spell that targets only a single creature to Muck Drubb. -SVar:TrigChange:AB$ ChangeTargets | Cost$ 0 | TargetType$ Spell | ValidTgts$ Card | Defined$ Self | TargetsSingleTarget$ True | TargetValidTargeting$ Creature +SVar:TrigChange:AB$ ChangeTargets | Cost$ 0 | TargetType$ Spell | ValidTgts$ Card | DefinedMagnet$ Self | TargetsSingleTarget$ True | TargetValidTargeting$ Creature K:Madness:2 B SVar:RemAIDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/muck_drubb.jpg diff --git a/forge-gui/res/cardsfolder/s/spellskite.txt b/forge-gui/res/cardsfolder/s/spellskite.txt index c8d1c7fbda8..9c22dd42750 100644 --- a/forge-gui/res/cardsfolder/s/spellskite.txt +++ b/forge-gui/res/cardsfolder/s/spellskite.txt @@ -2,6 +2,6 @@ Name:Spellskite ManaCost:2 Types:Artifact Creature Horror PT:0/4 -A:AB$ ChangeTargets | Cost$ PU | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card | Defined$ Self | ChangeSingleTarget$ True | SpellDescription$ Change a target of target spell or ability to Spellskite. +A:AB$ ChangeTargets | Cost$ PU | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card | DefinedMagnet$ Self | ChangeSingleTarget$ True | SpellDescription$ Change a target of target spell or ability to Spellskite. SVar:Picture:http://www.wizards.com/global/images/magic/general/spellskite.jpg Oracle:{U/P}: Change a target of target spell or ability to Spellskite. ({U/P} can be paid with either {U} or 2 life.) \ No newline at end of file