mirror of
https://github.com/correl/mage.git
synced 2025-04-09 01:01:06 -09:00
* Soulbond - Reworked to two triggerd abilities (fixes #1882).
This commit is contained in:
parent
3b98d0714d
commit
1dbba3f7a9
32 changed files with 374 additions and 285 deletions
Mage.Common/src/mage/view
Mage.Sets/src/mage/sets
avacynrestored
DeadeyeNavigator.javaDiregrafEscort.javaDruidsFamiliar.javaElgaudShieldmate.javaFloweringLumberknot.javaGalvanicAlchemist.javaGeistTrappers.javaHanweirLancer.javaJointAssault.javaLightningMauler.javaNearheathPilgrim.javaNightshadePeddler.javaPathbreakerWurm.javaSilverbladePaladin.javaSpectralGateguards.javaSternMentor.javaStonewright.javaTandemLookout.javaTrustedForcemage.javaWingcrafter.javaWolfirSilverheart.java
magic2012
Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords
Mage/src/main/java/mage
abilities
effects/common/continuous
keyword
game
players
watchers/common
|
@ -186,16 +186,14 @@ public class CardView extends SimpleCardView {
|
|||
this.rules.add("You may cast this card as a 2/2 face-down creature, with no text,"
|
||||
+ " no name, no subtypes, and no mana cost by paying {3} rather than paying its mana cost.");
|
||||
return;
|
||||
} else if (card instanceof Permanent) {
|
||||
this.power = Integer.toString(card.getPower().getValue());
|
||||
this.toughness = Integer.toString(card.getToughness().getValue());
|
||||
this.cardTypes = card.getCardType();
|
||||
this.faceDown = ((Permanent) card).isFaceDown(game);
|
||||
} else {
|
||||
if (card instanceof Permanent) {
|
||||
this.power = Integer.toString(card.getPower().getValue());
|
||||
this.toughness = Integer.toString(card.getToughness().getValue());
|
||||
this.cardTypes = card.getCardType();
|
||||
this.faceDown = ((Permanent) card).isFaceDown(game);
|
||||
} else {
|
||||
// this.hideInfo = true;
|
||||
return;
|
||||
}
|
||||
// this.hideInfo = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,18 +201,16 @@ public class CardView extends SimpleCardView {
|
|||
if (card.isSplitCard()) {
|
||||
splitCard = (SplitCard) card;
|
||||
rotate = true;
|
||||
} else {
|
||||
if (card instanceof Spell) {
|
||||
switch (((Spell) card).getSpellAbility().getSpellAbilityType()) {
|
||||
case SPLIT_FUSED:
|
||||
splitCard = (SplitCard) ((Spell) card).getCard();
|
||||
rotate = true;
|
||||
break;
|
||||
case SPLIT_LEFT:
|
||||
case SPLIT_RIGHT:
|
||||
rotate = true;
|
||||
break;
|
||||
}
|
||||
} else if (card instanceof Spell) {
|
||||
switch (((Spell) card).getSpellAbility().getSpellAbilityType()) {
|
||||
case SPLIT_FUSED:
|
||||
splitCard = (SplitCard) ((Spell) card).getCard();
|
||||
rotate = true;
|
||||
break;
|
||||
case SPLIT_LEFT:
|
||||
case SPLIT_RIGHT:
|
||||
rotate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (splitCard != null) {
|
||||
|
@ -241,7 +237,7 @@ public class CardView extends SimpleCardView {
|
|||
this.mageObjectType = MageObjectType.PERMANENT;
|
||||
Permanent permanent = (Permanent) card;
|
||||
this.loyalty = Integer.toString(permanent.getCounters().getCount(CounterType.LOYALTY));
|
||||
this.pairedCard = permanent.getPairedCard();
|
||||
this.pairedCard = permanent.getPairedCard() != null ? permanent.getPairedCard().getSourceId() : null;
|
||||
if (!permanent.getControllerId().equals(permanent.getOwnerId())) {
|
||||
controlledByOwner = false;
|
||||
}
|
||||
|
@ -421,12 +417,10 @@ public class CardView extends SimpleCardView {
|
|||
if (card != null) {
|
||||
if (card instanceof Permanent) {
|
||||
this.mageObjectType = MageObjectType.PERMANENT;
|
||||
} else if (card.isCopy()) {
|
||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||
} else {
|
||||
if (card.isCopy()) {
|
||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||
} else {
|
||||
this.mageObjectType = MageObjectType.CARD;
|
||||
}
|
||||
this.mageObjectType = MageObjectType.CARD;
|
||||
}
|
||||
if (card instanceof PermanentToken) {
|
||||
this.mageObjectType = MageObjectType.TOKEN;
|
||||
|
|
|
@ -58,7 +58,7 @@ public class DeadeyeNavigator extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Deadeye Navigator is paired with another creature, each of those creatures has "{1}{U}: Exile this creature, then return it to the battlefield under your control."
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileSourceEffect(true), new ManaCostsImpl("{1}{U}"));
|
||||
|
|
|
@ -64,7 +64,7 @@ public class DiregrafEscort extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Diregraf Escort is paired with another creature, both creatures have protection from Zombies.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(new ProtectionAbility(filter), ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class DruidsFamiliar extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Druid's Familiar is paired with another creature, each of those creatures gets +2/+2.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostPairedEffect(2, 2, ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ElgaudShieldmate extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Elgaud Shieldmate is paired with another creature, both creatures have hexproof.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(HexproofAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -27,21 +27,20 @@
|
|||
*/
|
||||
package mage.sets.avacynrestored;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.keyword.SoulbondAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
|
@ -83,17 +82,26 @@ class FloweringLumberknotEffect extends RestrictionEffect {
|
|||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
if (permanent.getId().equals(source.getSourceId())) {
|
||||
if (permanent.getPairedCard() == null) {
|
||||
return true; // not paired => can't attack or block
|
||||
if (permanent.getPairedCard() != null) {
|
||||
Permanent paired = permanent.getPairedCard().getPermanent(game);
|
||||
if (paired != null) {
|
||||
boolean found = false;
|
||||
for (Ability ability : paired.getAbilities(game)) {
|
||||
if (ability instanceof SoulbondAbility) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return false;// paired => can attack or block
|
||||
}
|
||||
}
|
||||
}
|
||||
Permanent paired = game.getPermanent(permanent.getPairedCard());
|
||||
if (paired != null && paired.getAbilities().contains(SoulbondAbility.getInstance())) {
|
||||
return false; // paired => can attack or block
|
||||
}
|
||||
// can't attack or block otherwise
|
||||
// can't attack or block
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -58,7 +58,7 @@ public class GalvanicAlchemist extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Galvanic Alchemist is paired with another creature, each of those creatures has "{2}{U}: Untap this creature."
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), new ManaCostsImpl("{2}{U}"));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class GeistTrappers extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Geist Trappers is paired with another creature, both creatures have reach.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(ReachAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class HanweirLancer extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Hanweir Lancer is paired with another creature, both creatures have first strike.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(FirstStrikeAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -27,21 +27,21 @@
|
|||
*/
|
||||
package mage.sets.avacynrestored;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import java.util.UUID;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
|
@ -51,7 +51,6 @@ public class JointAssault extends CardImpl {
|
|||
super(ownerId, 183, "Joint Assault", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G}");
|
||||
this.expansionSetCode = "AVR";
|
||||
|
||||
|
||||
// Target creature gets +2/+2 until end of turn. If it's paired with a creature, that creature also gets +2/+2 until end of turn.
|
||||
this.getSpellAbility().addEffect(new JointAssaultBoostTargetEffect(2, 2, Duration.EndOfTurn));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
|
@ -69,9 +68,9 @@ public class JointAssault extends CardImpl {
|
|||
|
||||
class JointAssaultBoostTargetEffect extends ContinuousEffectImpl {
|
||||
|
||||
private int power;
|
||||
private int toughness;
|
||||
private UUID paired;
|
||||
private final int power;
|
||||
private final int toughness;
|
||||
private MageObjectReference paired;
|
||||
|
||||
public JointAssaultBoostTargetEffect(int power, int toughness, Duration duration) {
|
||||
super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
|
||||
|
@ -116,10 +115,10 @@ class JointAssaultBoostTargetEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
|
||||
if (this.paired != null) {
|
||||
Permanent paired = game.getPermanent(this.paired);
|
||||
if (paired != null) {
|
||||
paired.addPower(power);
|
||||
paired.addToughness(toughness);
|
||||
Permanent pairedPermanent = this.paired.getPermanent(game);
|
||||
if (pairedPermanent != null) {
|
||||
pairedPermanent.addPower(power);
|
||||
pairedPermanent.addToughness(toughness);
|
||||
affectedTargets++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class LightningMauler extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Lightning Mauler is paired with another creature, both creatures have haste.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(HasteAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class NearheathPilgrim extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Nearheath Pilgrim is paired with another creature, both creatures have lifelink.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(LifelinkAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class NightshadePeddler extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Nightshade Peddler is paired with another creature, both creatures have deathtouch.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(DeathtouchAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -54,7 +54,7 @@ public class PathbreakerWurm extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Pathbreaker Wurm is paired with another creature, both creatures have trample.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(TrampleAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SilverbladePaladin extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Silverblade Paladin is paired with another creature, both creatures have double strike.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(DoubleStrikeAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SpectralGateguards extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Spectral Gateguards is paired with another creature, both creatures have vigilance.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(VigilanceAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -59,7 +59,7 @@ public class SternMentor extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Stern Mentor is paired with another creature, each of those creatures has "{T}: Target player puts the top two cards of his or her library into his or her graveyard."
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(2), new TapSourceCost());
|
||||
|
|
|
@ -59,7 +59,7 @@ public class Stonewright extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Stonewright is paired with another creature, each of those creatures has "{R}: This creature gets +1/+0 until end of turn."
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}"));
|
||||
|
|
|
@ -57,7 +57,7 @@ public class TandemLookout extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Tandem Lookout is paired with another creature, each of those creatures has "Whenever this creature deals damage to an opponent, draw a card."
|
||||
Ability ability = new DealsDamageToOpponentTriggeredAbility(new DrawCardSourceControllerEffect(1));
|
||||
|
|
|
@ -54,7 +54,7 @@ public class TrustedForcemage extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Trusted Forcemage is paired with another creature, each of those creatures gets +1/+1.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostPairedEffect(1, 1, ruleText)));
|
||||
|
|
|
@ -57,7 +57,7 @@ public class Wingcrafter extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Wingcrafter is paired with another creature, both creatures have flying.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityPairedEffect(FlyingAbility.getInstance(), ruleText)));
|
||||
|
|
|
@ -54,7 +54,7 @@ public class WolfirSilverheart extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// Soulbond
|
||||
this.addAbility(SoulbondAbility.getInstance());
|
||||
this.addAbility(new SoulbondAbility());
|
||||
|
||||
// As long as Wolfir Silverheart is paired with another creature, each of those creatures gets +4/+4.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostPairedEffect(4, 4, ruleText)));
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
package mage.sets.magic2012;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.BecomesTargetTriggeredAbility;
|
||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -50,6 +50,7 @@ public class PhantasmalBear extends CardImpl {
|
|||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// When Phantasmal Bear becomes the target of a spell or ability, sacrifice it.
|
||||
this.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()));
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import mage.constants.Zone;
|
|||
import mage.filter.Filter;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
@ -318,9 +317,12 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
|
|||
*/
|
||||
@Test
|
||||
public void testRebondOnNextCreature() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
// When Phantasmal Bear becomes the target of a spell or ability, sacrifice it.
|
||||
addCard(Zone.HAND, playerA, "Phantasmal Bear");
|
||||
// Soulbond
|
||||
// As long as Trusted Forcemage is paired with another creature, each of those creatures gets +1/+1.
|
||||
addCard(Zone.HAND, playerA, "Trusted Forcemage");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); // 2/1
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
|
@ -329,10 +331,10 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
|
|||
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Trusted Forcemage");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Elite Vanguard");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phantasmal Bear");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Elite Vanguard");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Phantasmal Bear");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Elite Vanguard", 0);
|
||||
|
@ -347,7 +349,9 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
|
|||
*/
|
||||
@Test
|
||||
public void testGrantingAbility() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); // 2/1
|
||||
// Soulbond
|
||||
// As long as Nearheath Pilgrim is paired with another creature, both creatures have lifelink.
|
||||
addCard(Zone.HAND, playerA, "Nearheath Pilgrim");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
|
||||
|
@ -391,42 +395,39 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
|
|||
Assert.assertEquals(trustedForcemange.getPairedCard(), null);
|
||||
Assert.assertEquals(eliteVanguard.getPairedCard(), null);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reported bug: Soulbond should use the stack, but unable to use instant speed removal since no trigger occurs
|
||||
*/
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
// Soulbond does not currently use the stack, so this test will fail until then
|
||||
public void testRespondToSoulboundWithRemoval() {
|
||||
|
||||
|
||||
// When Palinchron enters the battlefield, untap up to seven lands.
|
||||
// {2}{U}{U}: Return Palinchron to its owner's hand.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Palinchron"); // 4/5 flying
|
||||
|
||||
|
||||
// Soulbond
|
||||
// As long as Deadeye Navigator is paired with another creature, each of those creatures has "{1}{U}: Exile this creature, then return it to the battlefield under your control."
|
||||
addCard(Zone.HAND, playerA, "Deadeye Navigator"); // 5/5
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Doom Blade", 1); // {1}{B} instant: Destroy target non-black creature
|
||||
addCard(Zone.HAND, playerB, "Doom Blade", 1); // {1}{B} instant: Destroy target non-black creature
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Deadeye Navigator");
|
||||
setChoice(playerA, "Yes");
|
||||
addTarget(playerA, "Palinchron");
|
||||
setChoice(playerA, "Palinchron");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Doom Blade", "Deadeye Navigator");
|
||||
|
||||
// Deadeye's ability should not be usable since was Destroyed before Soulbond trigger resolved
|
||||
|
||||
// Deadeye's ability should not be usable since was destroyed before Soulbond trigger resolved
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{U}:");
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
Permanent palinchron = getPermanent("Palinchron", playerA);
|
||||
Permanent deadeye = getPermanent("Deadeye Navigator", playerA);
|
||||
Assert.assertEquals(null, palinchron.getPairedCard()); // should not be paired
|
||||
Assert.assertEquals(null, deadeye.getPairedCard()); // should not be paired
|
||||
assertGraveyardCount(playerA, "Deadeye Navigator", 1);
|
||||
assertGraveyardCount(playerB, "Doom Blade", 1);
|
||||
assertGraveyardCount(playerA, "Deadeye Navigator", 1);
|
||||
assertGraveyardCount(playerB, "Doom Blade", 1);
|
||||
assertPermanentCount(playerA, "Palinchron", 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,16 +24,15 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
@ -68,7 +67,7 @@ public class BoostPairedEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && permanent.getPairedCard() != null) {
|
||||
Permanent paired = game.getPermanent(permanent.getPairedCard());
|
||||
Permanent paired = permanent.getPairedCard().getPermanent(game);
|
||||
if (paired != null) {
|
||||
permanent.addPower(power);
|
||||
permanent.addToughness(toughness);
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,20 +20,20 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
@ -66,11 +66,15 @@ public class GainAbilityPairedEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && permanent.getPairedCard() != null) {
|
||||
Permanent paired = game.getPermanent(permanent.getPairedCard());
|
||||
if (paired != null) {
|
||||
permanent.addAbility(ability, game);
|
||||
Permanent paired = permanent.getPairedCard().getPermanent(game);
|
||||
if (paired != null && paired.getPairedCard() != null && paired.getPairedCard().equals(new MageObjectReference(permanent, game))) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
paired.addAbility(ability, source.getSourceId(), game, false);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// No longer the same cards as orininally paired.
|
||||
permanent.setPairedCard(null);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -24,32 +24,71 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
* 702.94. Soulbond
|
||||
*
|
||||
* 702.94a Soulbond is a keyword that represents two triggered abilities.
|
||||
* “Soulbond” means “When this creature enters the battlefield, if you control
|
||||
* both this creature and another creature and both are unpaired, you may pair
|
||||
* this creature with another unpaired creature you control for as long as both
|
||||
* remain creatures on the battlefield under your control” and “Whenever another
|
||||
* creature enters the battlefield under your control, if you control both that
|
||||
* creature and this one and both are unpaired, you may pair that creature with
|
||||
* this creature for as long as both remain creatures on the battlefield under
|
||||
* your control.”
|
||||
*
|
||||
* 702.94b A creature becomes “paired” with another as the result of a soulbond
|
||||
* ability. Abilities may refer to a paired creature, the creature another
|
||||
* creature is paired with, or whether a creature is paired. An “unpaired”
|
||||
* creature is one that is not paired.
|
||||
*
|
||||
* 702.94c When the soulbond ability resolves, if either object that would be
|
||||
* paired is no longer a creature, no longer on the battlefield, or no longer
|
||||
* under the control of the player who controls the soulbond ability, neither
|
||||
* object becomes paired.
|
||||
*
|
||||
* 702.94d A creature can be paired with only one other creature.
|
||||
*
|
||||
* 702.94e A paired creature becomes unpaired if any of the following occur:
|
||||
* another player gains control of it or the creature it’s paired with; it or
|
||||
* the creature it’s paired with stops being a creature; or it or the creature
|
||||
* it’s paired with leaves the battlefield.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class SoulbondAbility extends StaticAbility implements MageSingleton {
|
||||
public class SoulbondAbility extends EntersBattlefieldTriggeredAbility {
|
||||
|
||||
private static final SoulbondAbility fINSTANCE = new SoulbondAbility();
|
||||
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return fINSTANCE;
|
||||
public SoulbondAbility() {
|
||||
super(new SoulboundEntersSelfEffect(), true);
|
||||
this.addSubAbility(new SoulbondEntersOtherAbility());
|
||||
}
|
||||
|
||||
public static SoulbondAbility getInstance() {
|
||||
return fINSTANCE;
|
||||
}
|
||||
|
||||
private SoulbondAbility() {
|
||||
super(Zone.BATTLEFIELD, null);
|
||||
public SoulbondAbility(SoulbondAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,9 +96,200 @@ public class SoulbondAbility extends StaticAbility implements MageSingleton {
|
|||
return "Soulbond <i>(You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.)</i>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
// if you control both this creature and another creature and both are unpaired
|
||||
boolean self = false;
|
||||
boolean other = false;
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(getControllerId())) {
|
||||
if (permanent.getCardType().contains(CardType.CREATURE)) {
|
||||
if (permanent.getId().equals(getSourceId())) {
|
||||
if (permanent.getControllerId().equals(getControllerId())) {
|
||||
self = true;
|
||||
if (other) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (permanent.getPairedCard() == null) {
|
||||
other = true;
|
||||
if (self) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoulbondAbility copy() {
|
||||
return fINSTANCE;
|
||||
return new SoulbondAbility(this);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// When this creature enters the battlefield, if you control both this creature and another creature and both are unpaired, you may pair
|
||||
// this creature with another unpaired creature you control for as long as both remain creatures on the battlefield under your control
|
||||
|
||||
class SoulboundEntersSelfEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control");
|
||||
|
||||
static {
|
||||
filter.add(new AnotherPredicate());
|
||||
filter.add(Predicates.not(new PairedPredicate()));
|
||||
}
|
||||
|
||||
public SoulboundEntersSelfEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
public SoulboundEntersSelfEffect(final SoulboundEntersSelfEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoulboundEntersSelfEffect copy() {
|
||||
return new SoulboundEntersSelfEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) {
|
||||
Player controller = game.getPlayer(permanent.getControllerId());
|
||||
if (controller != null) {
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(filter);
|
||||
target.setNotTarget(true);
|
||||
if (target.canChoose(permanent.getId(), controller.getId(), game)) {
|
||||
if (controller.choose(Outcome.Benefit, target, permanent.getId(), game)) {
|
||||
Permanent chosen = game.getPermanent(target.getFirstTarget());
|
||||
if (chosen != null) {
|
||||
chosen.setPairedCard(new MageObjectReference(permanent, game));
|
||||
permanent.setPairedCard(new MageObjectReference(chosen, game));
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " soulbonds " + permanent.getLogName() + " with " + chosen.getLogName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* “Whenever another creature enters the battlefield under your control, if you
|
||||
* control both that creature and this one and both are unpaired, you may pair
|
||||
* that creature with this creature for as long as both remain creatures on the
|
||||
* battlefield under your control.”
|
||||
*
|
||||
*/
|
||||
class SoulbondEntersOtherAbility extends EntersBattlefieldAllTriggeredAbility {
|
||||
|
||||
private final static FilterCreaturePermanent soulbondFilter = new FilterCreaturePermanent();
|
||||
|
||||
static {
|
||||
soulbondFilter.add(Predicates.not(new PairedPredicate()));
|
||||
soulbondFilter.add(new ControllerPredicate(TargetController.YOU));
|
||||
soulbondFilter.add(new AnotherPredicate());
|
||||
}
|
||||
|
||||
public SoulbondEntersOtherAbility() {
|
||||
super(Zone.BATTLEFIELD, new SoulboundEntersOtherEffect(), soulbondFilter, true, SetTargetPointer.PERMANENT, "");
|
||||
setRuleVisible(false);
|
||||
}
|
||||
|
||||
public SoulbondEntersOtherAbility(SoulbondEntersOtherAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Soulbond <i>(You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.)</i>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
// if you control both this creature and another creature and both are unpaired
|
||||
if (game.getBattlefield().countAll(filter, getControllerId(), game) > 0) {
|
||||
Permanent sourcePermanent = game.getPermanent(getSourceId());
|
||||
if (sourcePermanent != null && sourcePermanent.getControllerId().equals(getControllerId()) && sourcePermanent.getPairedCard() == null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoulbondEntersOtherAbility copy() {
|
||||
return new SoulbondEntersOtherAbility(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SoulboundEntersOtherEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control");
|
||||
|
||||
static {
|
||||
filter.add(new AnotherPredicate());
|
||||
filter.add(Predicates.not(new PairedPredicate()));
|
||||
}
|
||||
|
||||
public SoulboundEntersOtherEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
public SoulboundEntersOtherEffect(final SoulboundEntersOtherEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoulboundEntersOtherEffect copy() {
|
||||
return new SoulboundEntersOtherEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && permanent.getPairedCard() == null
|
||||
&& permanent.getCardType().contains(CardType.CREATURE)) {
|
||||
Player controller = game.getPlayer(permanent.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent enteringPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (enteringPermanent != null && enteringPermanent.getCardType().contains(CardType.CREATURE) && enteringPermanent.getPairedCard() == null) {
|
||||
enteringPermanent.setPairedCard(new MageObjectReference(permanent, game));
|
||||
permanent.setPairedCard(new MageObjectReference(enteringPermanent, game));
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " soulbonds " + permanent.getLogName() + " with " + enteringPermanent.getLogName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PairedPredicate implements Predicate<Permanent> {
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return input.getPairedCard() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Paired";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -131,7 +131,6 @@ import mage.watchers.common.DamageDoneWatcher;
|
|||
import mage.watchers.common.MorbidWatcher;
|
||||
import mage.watchers.common.PlayerDamagedBySourceWatcher;
|
||||
import mage.watchers.common.PlayerLostLifeWatcher;
|
||||
import mage.watchers.common.SoulbondWatcher;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public abstract class GameImpl implements Game, Serializable {
|
||||
|
@ -1007,7 +1006,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
watchers.add(new MorbidWatcher());
|
||||
watchers.add(new CastSpellLastTurnWatcher());
|
||||
watchers.add(new SoulbondWatcher());
|
||||
watchers.add(new PlayerLostLifeWatcher());
|
||||
watchers.add(new BlockedAttackerWatcher());
|
||||
watchers.add(new DamageDoneWatcher());
|
||||
|
@ -1687,7 +1685,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (perm.getPairedCard() != null) {
|
||||
//702.93e.: ...another player gains control
|
||||
// ...or the creature it's paired with leaves the battlefield.
|
||||
Permanent paired = getPermanent(perm.getPairedCard());
|
||||
Permanent paired = perm.getPairedCard().getPermanent(this);
|
||||
if (paired == null || !perm.getControllerId().equals(paired.getControllerId()) || paired.getPairedCard() == null) {
|
||||
perm.setPairedCard(null);
|
||||
if (paired != null) {
|
||||
|
@ -1698,7 +1696,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
} else if (perm.getPairedCard() != null) {
|
||||
//702.93e.: ...stops being a creature
|
||||
Permanent paired = getPermanent(perm.getPairedCard());
|
||||
Permanent paired = perm.getPairedCard().getPermanent(this);
|
||||
perm.setPairedCard(null);
|
||||
if (paired != null) {
|
||||
paired.setPairedCard(null);
|
||||
|
|
|
@ -327,14 +327,14 @@ public interface Permanent extends Card, Controllable {
|
|||
*
|
||||
* @param pairedCard
|
||||
*/
|
||||
void setPairedCard(UUID pairedCard);
|
||||
void setPairedCard(MageObjectReference pairedCard);
|
||||
|
||||
/**
|
||||
* Gets paired card. Can return null.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
UUID getPairedCard();
|
||||
MageObjectReference getPairedCard();
|
||||
|
||||
/**
|
||||
* Makes permanent paired with no other permanent.
|
||||
|
|
|
@ -116,7 +116,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
protected HashSet<MageObjectReference> dealtDamageByThisTurn;
|
||||
protected UUID attachedTo;
|
||||
protected int attachedToZoneChangeCounter;
|
||||
protected UUID pairedCard;
|
||||
protected MageObjectReference pairedPermanent;
|
||||
protected Counters counters;
|
||||
protected List<Counter> markedDamage;
|
||||
protected int timesLoyaltyUsed = 0;
|
||||
|
@ -179,7 +179,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.transformed = permanent.transformed;
|
||||
this.monstrous = permanent.monstrous;
|
||||
this.renowned = permanent.renowned;
|
||||
this.pairedCard = permanent.pairedCard;
|
||||
this.pairedPermanent = permanent.pairedPermanent;
|
||||
this.timesLoyaltyUsed = permanent.timesLoyaltyUsed;
|
||||
|
||||
this.morphed = permanent.morphed;
|
||||
|
@ -1318,18 +1318,18 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setPairedCard(UUID pairedCard) {
|
||||
this.pairedCard = pairedCard;
|
||||
public void setPairedCard(MageObjectReference pairedCard) {
|
||||
this.pairedPermanent = pairedCard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getPairedCard() {
|
||||
return pairedCard;
|
||||
public MageObjectReference getPairedCard() {
|
||||
return pairedPermanent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearPairedCard() {
|
||||
this.pairedCard = null;
|
||||
this.pairedPermanent = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -839,7 +839,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
}
|
||||
if (permanent.getPairedCard() != null) {
|
||||
Permanent pairedCard = game.getPermanent(permanent.getPairedCard());
|
||||
Permanent pairedCard = permanent.getPairedCard().getPermanent(game);
|
||||
if (pairedCard != null) {
|
||||
pairedCard.clearPairedCard();
|
||||
}
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.watchers.common;
|
||||
|
||||
import mage.abilities.keyword.SoulbondAbility;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
* Reacts on various events to pair or unpair creatures on the battlefield.
|
||||
*
|
||||
* @author noxx
|
||||
*/
|
||||
public class SoulbondWatcher extends Watcher {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another not paired creature you control");
|
||||
|
||||
static {
|
||||
filter.add(new AnotherPredicate());
|
||||
filter.add(Predicates.not(new PairedPredicate()));
|
||||
}
|
||||
|
||||
public SoulbondWatcher() {
|
||||
super("SoulbondWatcher", WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public SoulbondWatcher(final SoulbondWatcher watcher) {
|
||||
super(watcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||
if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) {
|
||||
if (permanent.getAbilities().contains(SoulbondAbility.getInstance())) {
|
||||
Player controller = game.getPlayer(permanent.getControllerId());
|
||||
if (controller != null) {
|
||||
Cards cards = new CardsImpl();
|
||||
cards.add(permanent);
|
||||
controller.lookAtCards("Soulbond", cards, game);
|
||||
if (controller.chooseUse(Outcome.Benefit, "Use Soulbond?", null, game)) {
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(filter);
|
||||
target.setNotTarget(true);
|
||||
if (target.canChoose(permanent.getId(), controller.getId(), game)) {
|
||||
if (controller.choose(Outcome.Benefit, target, permanent.getId(), game)) {
|
||||
Permanent chosen = game.getPermanent(target.getFirstTarget());
|
||||
if (chosen != null) {
|
||||
chosen.setPairedCard(permanent.getId());
|
||||
permanent.setPairedCard(chosen.getId());
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(new StringBuilder(controller.getLogName()).append(" souldbonds ").append(permanent.getLogName()).append(" with ").append(chosen.getName()).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if still unpaired
|
||||
if (permanent.getPairedCard() == null) {
|
||||
// try to find creature with Soulbond and unpaired
|
||||
Player controller = null;
|
||||
for (Permanent chosen : game.getBattlefield().getActivePermanents(filter, permanent.getControllerId(), permanent.getId(), game)) {
|
||||
if (!chosen.getId().equals(permanent.getId()) && chosen.getAbilities().contains(SoulbondAbility.getInstance()) && chosen.getPairedCard() == null) {
|
||||
if (controller == null) {
|
||||
controller = game.getPlayer(permanent.getControllerId());
|
||||
}
|
||||
if (controller != null) {
|
||||
Cards cards = new CardsImpl();
|
||||
cards.add(chosen);
|
||||
controller.lookAtCards("Soulbond", cards, game);
|
||||
if (controller.chooseUse(Outcome.Benefit, "Use Soulbond for recent " + permanent.getLogName() + "?", SoulbondAbility.getInstance(), game)) {
|
||||
chosen.setPairedCard(permanent.getId());
|
||||
permanent.setPairedCard(chosen.getId());
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(new StringBuilder(controller.getLogName()).append(" souldbonds ").append(permanent.getLogName()).append(" with ").append(chosen.getName()).toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoulbondWatcher copy() {
|
||||
return new SoulbondWatcher(this);
|
||||
}
|
||||
}
|
||||
|
||||
class PairedPredicate implements Predicate<Permanent> {
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return input.getPairedCard() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Paired";
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue