forked from External/mage
Implement The Ring Tempts You mechanic (#10320)
* remove skip * initial implementation of the ring mechanic * some changes * rework ring-bearer choosing * [LTR] Implement Call of the Ring * update ring-bearer condition
This commit is contained in:
parent
d56c148118
commit
3503513c4e
19 changed files with 508 additions and 48 deletions
71
Mage.Sets/src/mage/cards/c/CallOfTheRing.java
Normal file
71
Mage.Sets/src/mage/cards/c/CallOfTheRing.java
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||||
|
import mage.abilities.costs.common.PayLifeCost;
|
||||||
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.abilities.effects.keyword.TheRingTemptsYouEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.TargetController;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class CallOfTheRing extends CardImpl {
|
||||||
|
|
||||||
|
public CallOfTheRing(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}");
|
||||||
|
|
||||||
|
// At the beginning of your upkeep, the Ring tempts you.
|
||||||
|
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
|
||||||
|
new TheRingTemptsYouEffect(), TargetController.YOU, false
|
||||||
|
));
|
||||||
|
|
||||||
|
// Whenever you choose a creature as your Ring-bearer, you may pay 2 life. If you do, draw a card.
|
||||||
|
this.addAbility(new CallOfTheRingTriggeredAbility());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CallOfTheRing(final CallOfTheRing card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CallOfTheRing copy() {
|
||||||
|
return new CallOfTheRing(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallOfTheRingTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
CallOfTheRingTriggeredAbility() {
|
||||||
|
super(Zone.BATTLEFIELD, new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new PayLifeCost(2)));
|
||||||
|
setTriggerPhrase("Whenever you choose a creature as your Ring-bearer, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private CallOfTheRingTriggeredAbility(final CallOfTheRingTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CallOfTheRingTriggeredAbility copy() {
|
||||||
|
return new CallOfTheRingTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.RING_BEARER_CHOSEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
return isControlledBy(event.getPlayerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
package mage.cards.f;
|
package mage.cards.f;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.common.SourceIsRingBearerCondition;
|
||||||
import mage.abilities.decorator.ConditionalRequirementEffect;
|
import mage.abilities.decorator.ConditionalRequirementEffect;
|
||||||
import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect;
|
import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect;
|
||||||
import mage.abilities.effects.keyword.TheRingTemptsYouEffect;
|
import mage.abilities.effects.keyword.TheRingTemptsYouEffect;
|
||||||
|
|
@ -15,7 +14,6 @@ import mage.constants.SubType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.game.Game;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ public final class FrodoBaggins extends CardImpl {
|
||||||
|
|
||||||
// As long as Frodo is your Ring-bearer, it must be blocked if able.
|
// As long as Frodo is your Ring-bearer, it must be blocked if able.
|
||||||
this.addAbility(new SimpleStaticAbility(new ConditionalRequirementEffect(
|
this.addAbility(new SimpleStaticAbility(new ConditionalRequirementEffect(
|
||||||
new MustBeBlockedByAtLeastOneSourceEffect(), FrodoBagginsCondition.instance,
|
new MustBeBlockedByAtLeastOneSourceEffect(), SourceIsRingBearerCondition.instance,
|
||||||
"as long as {this} is your Ring-bearer, it must be blocked if able"
|
"as long as {this} is your Ring-bearer, it must be blocked if able"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
@ -60,13 +58,3 @@ public final class FrodoBaggins extends CardImpl {
|
||||||
return new FrodoBaggins(this);
|
return new FrodoBaggins(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FrodoBagginsCondition implements Condition {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
// TODO: Implement this
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -19,6 +19,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.watchers.common.TemptedByTheRingWatcher;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -80,7 +81,6 @@ enum FrodoSauronsBaneCondition implements Condition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
// TODO: Implement when mechanic is known
|
return TemptedByTheRingWatcher.getCount(source.getControllerId(), game) >= 4;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksTriggeredAbility;
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.condition.InvertCondition;
|
||||||
|
import mage.abilities.condition.common.SourceIsRingBearerCondition;
|
||||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||||
|
|
@ -38,7 +40,7 @@ public final class SauronTheNecromancer extends CardImpl {
|
||||||
this.toughness = new MageInt(4);
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(new MenaceAbility());
|
this.addAbility(new MenaceAbility(false));
|
||||||
|
|
||||||
// Whenever Sauron, the Necromancer attacks, exile target creature card from your graveyard. Create a tapped and attacking token that's a copy of that card, except it's a 3/3 black Wraith with menace. At the beginning of the next end step, exile that token unless Sauron is your Ring-bearer.
|
// Whenever Sauron, the Necromancer attacks, exile target creature card from your graveyard. Create a tapped and attacking token that's a copy of that card, except it's a 3/3 black Wraith with menace. At the beginning of the next end step, exile that token unless Sauron is your Ring-bearer.
|
||||||
Ability ability = new AttacksTriggeredAbility(new SauronTheNecromancerEffect());
|
Ability ability = new AttacksTriggeredAbility(new SauronTheNecromancerEffect());
|
||||||
|
|
@ -56,18 +58,10 @@ public final class SauronTheNecromancer extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SauronTheNecromancerCondition implements Condition {
|
|
||||||
instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
// TODO: Implement this
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SauronTheNecromancerEffect extends OneShotEffect {
|
class SauronTheNecromancerEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
private static final Condition condition = new InvertCondition(SourceIsRingBearerCondition.instance);
|
||||||
|
|
||||||
SauronTheNecromancerEffect() {
|
SauronTheNecromancerEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
staticText = "exile target creature card from your graveyard. Create a tapped and attacking " +
|
staticText = "exile target creature card from your graveyard. Create a tapped and attacking " +
|
||||||
|
|
@ -105,7 +99,7 @@ class SauronTheNecromancerEffect extends OneShotEffect {
|
||||||
effect.apply(game, source);
|
effect.apply(game, source);
|
||||||
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
|
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
|
||||||
new ConditionalOneShotEffect(
|
new ConditionalOneShotEffect(
|
||||||
new ExileTargetEffect(), SauronTheNecromancerCondition.instance,
|
new ExileTargetEffect(), condition,
|
||||||
"exile that token unless {this} is your Ring-bearer"
|
"exile that token unless {this} is your Ring-bearer"
|
||||||
).setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game))
|
).setTargetPointer(new FixedTargets(effect.getAddedPermanents(), game))
|
||||||
), source);
|
), source);
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,8 @@ import mage.cards.ExpansionSet;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SetType;
|
import mage.constants.SetType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet {
|
public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet {
|
||||||
|
|
||||||
private static final List<String> unfinished = Arrays.asList("Bilbo, Retired Burglar", "Call of the Ring", "Frodo Baggins", "Frodo, Sauron's Bane", "Gollum, Patient Plotter", "Samwise the Stouthearted");
|
|
||||||
private static final TheLordOfTheRingsTalesOfMiddleEarth instance = new TheLordOfTheRingsTalesOfMiddleEarth();
|
private static final TheLordOfTheRingsTalesOfMiddleEarth instance = new TheLordOfTheRingsTalesOfMiddleEarth();
|
||||||
|
|
||||||
public static TheLordOfTheRingsTalesOfMiddleEarth getInstance() {
|
public static TheLordOfTheRingsTalesOfMiddleEarth getInstance() {
|
||||||
|
|
@ -24,6 +20,7 @@ public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet {
|
||||||
|
|
||||||
cards.add(new SetCardInfo("Aragorn and Arwen, Wed", 287, Rarity.MYTHIC, mage.cards.a.AragornAndArwenWed.class));
|
cards.add(new SetCardInfo("Aragorn and Arwen, Wed", 287, Rarity.MYTHIC, mage.cards.a.AragornAndArwenWed.class));
|
||||||
cards.add(new SetCardInfo("Bilbo, Retired Burglar", 403, Rarity.UNCOMMON, mage.cards.b.BilboRetiredBurglar.class));
|
cards.add(new SetCardInfo("Bilbo, Retired Burglar", 403, Rarity.UNCOMMON, mage.cards.b.BilboRetiredBurglar.class));
|
||||||
|
cards.add(new SetCardInfo("Call of the Ring", 79, Rarity.RARE, mage.cards.c.CallOfTheRing.class));
|
||||||
cards.add(new SetCardInfo("Forest", 280, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
cards.add(new SetCardInfo("Forest", 280, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Frodo Baggins", 404, Rarity.UNCOMMON, mage.cards.f.FrodoBaggins.class));
|
cards.add(new SetCardInfo("Frodo Baggins", 404, Rarity.UNCOMMON, mage.cards.f.FrodoBaggins.class));
|
||||||
cards.add(new SetCardInfo("Frodo, Sauron's Bane", 18, Rarity.RARE, mage.cards.f.FrodoSauronsBane.class));
|
cards.add(new SetCardInfo("Frodo, Sauron's Bane", 18, Rarity.RARE, mage.cards.f.FrodoSauronsBane.class));
|
||||||
|
|
@ -45,7 +42,5 @@ public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Trailblazer's Boots", 398, Rarity.RARE, mage.cards.t.TrailblazersBoots.class));
|
cards.add(new SetCardInfo("Trailblazer's Boots", 398, Rarity.RARE, mage.cards.t.TrailblazersBoots.class));
|
||||||
cards.add(new SetCardInfo("Wizard's Rockets", 400, Rarity.COMMON, mage.cards.w.WizardsRockets.class));
|
cards.add(new SetCardInfo("Wizard's Rockets", 400, Rarity.COMMON, mage.cards.w.WizardsRockets.class));
|
||||||
cards.add(new SetCardInfo("You Cannot Pass!", 38, Rarity.UNCOMMON, mage.cards.y.YouCannotPass.class));
|
cards.add(new SetCardInfo("You Cannot Pass!", 38, Rarity.UNCOMMON, mage.cards.y.YouCannotPass.class));
|
||||||
|
|
||||||
cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName())); // remove when mechanic is implemented
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4361,6 +4361,21 @@ public class TestPlayer implements Player {
|
||||||
return computerPlayer.getPhyrexianColors();
|
return computerPlayer.getPhyrexianColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getRingBearerId() {
|
||||||
|
return computerPlayer.getRingBearerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Permanent getRingBearer(Game game) {
|
||||||
|
return computerPlayer.getRingBearer(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chooseRingBearer(Game game) {
|
||||||
|
computerPlayer.chooseRingBearer(game);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) {
|
||||||
assertAliasSupportInChoices(false);
|
assertAliasSupportInChoices(false);
|
||||||
|
|
|
||||||
|
|
@ -1419,6 +1419,20 @@ public class PlayerStub implements Player {
|
||||||
return (new FilterMana());
|
return (new FilterMana());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getRingBearerId() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Permanent getRingBearer(Game game) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chooseRingBearer(Game game) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserData getControllingPlayersUserData(Game game) {
|
public UserData getControllingPlayersUserData(Game game) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ import mage.MageObjectReference;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
@ -16,7 +17,7 @@ import mage.util.CardUtil;
|
||||||
*/
|
*/
|
||||||
public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityImpl {
|
public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
protected final FilterControlledCreaturePermanent filter;
|
protected final FilterPermanent filter;
|
||||||
protected final boolean setTargetPointer;
|
protected final boolean setTargetPointer;
|
||||||
protected boolean once = false;
|
protected boolean once = false;
|
||||||
|
|
||||||
|
|
@ -25,25 +26,29 @@ public class AttacksCreatureYouControlTriggeredAbility extends TriggeredAbilityI
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional) {
|
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional) {
|
||||||
this(effect, optional, new FilterControlledCreaturePermanent());
|
this(effect, optional, StaticFilters.FILTER_CONTROLLED_CREATURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer) {
|
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional, boolean setTargetPointer) {
|
||||||
this(effect, optional, new FilterControlledCreaturePermanent(), setTargetPointer);
|
this(effect, optional, StaticFilters.FILTER_CONTROLLED_CREATURE, setTargetPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional, FilterControlledCreaturePermanent filter) {
|
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter) {
|
||||||
this(effect, optional, filter, false);
|
this(effect, optional, filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional, FilterControlledCreaturePermanent filter, boolean setTargetPointer) {
|
public AttacksCreatureYouControlTriggeredAbility(Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) {
|
||||||
super(Zone.BATTLEFIELD, effect, optional);
|
this(Zone.BATTLEFIELD, effect, optional, filter, setTargetPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttacksCreatureYouControlTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) {
|
||||||
|
super(zone, effect, optional);
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.setTargetPointer = setTargetPointer;
|
this.setTargetPointer = setTargetPointer;
|
||||||
setTriggerPhrase("Whenever " + CardUtil.addArticle(filter.getMessage()) + " attacks, ");
|
setTriggerPhrase("Whenever " + CardUtil.addArticle(filter.getMessage()) + " attacks, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttacksCreatureYouControlTriggeredAbility(AttacksCreatureYouControlTriggeredAbility ability) {
|
private AttacksCreatureYouControlTriggeredAbility(final AttacksCreatureYouControlTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.filter = ability.filter;
|
this.filter = ability.filter;
|
||||||
this.setTargetPointer = ability.setTargetPointer;
|
this.setTargetPointer = ability.setTargetPointer;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package mage.abilities.condition.common;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.game.Game;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public enum SourceIsRingBearerCondition implements Condition {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return Optional
|
||||||
|
.ofNullable(source.getSourcePermanentIfItStillExists(game))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(permanent -> permanent.isControlledBy(source.getControllerId()))
|
||||||
|
.map(permanent -> permanent.isRingBearer(game))
|
||||||
|
.orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "{this} is your Ring-bearer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ public class TheRingTemptsYouEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
// TODO: Implement when we know what the mechanic does
|
game.temptWithTheRing(source.getControllerId());
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -406,6 +406,8 @@ public interface Game extends MageItem, Serializable, Copyable<Game> {
|
||||||
|
|
||||||
void ventureIntoDungeon(UUID playerId, boolean undercity);
|
void ventureIntoDungeon(UUID playerId, boolean undercity);
|
||||||
|
|
||||||
|
void temptWithTheRing(UUID playerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells whether the current game has day or night, defaults to false
|
* Tells whether the current game has day or night, defaults to false
|
||||||
*/
|
*/
|
||||||
|
|
@ -552,8 +554,8 @@ public interface Game extends MageItem, Serializable, Copyable<Game> {
|
||||||
/**
|
/**
|
||||||
* Function to call for a player to take the initiative.
|
* Function to call for a player to take the initiative.
|
||||||
*
|
*
|
||||||
* @param source The ability granting initiative.
|
* @param source The ability granting initiative.
|
||||||
* @param initiativeId UUID of the player taking the initiative
|
* @param initiativeId UUID of the player taking the initiative
|
||||||
*/
|
*/
|
||||||
void takeInitiative(Ability source, UUID initiativeId);
|
void takeInitiative(Ability source, UUID initiativeId);
|
||||||
|
|
||||||
|
|
@ -681,6 +683,6 @@ public interface Game extends MageItem, Serializable, Copyable<Game> {
|
||||||
void setGameStopped(boolean gameStopped);
|
void setGameStopped(boolean gameStopped);
|
||||||
|
|
||||||
boolean isGameStopped();
|
boolean isGameStopped();
|
||||||
|
|
||||||
boolean isTurnOrderReversed();
|
boolean isTurnOrderReversed();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import mage.game.combat.Combat;
|
||||||
import mage.game.combat.CombatGroup;
|
import mage.game.combat.CombatGroup;
|
||||||
import mage.game.command.*;
|
import mage.game.command.*;
|
||||||
import mage.game.command.dungeons.UndercityDungeon;
|
import mage.game.command.dungeons.UndercityDungeon;
|
||||||
|
import mage.game.command.emblems.TheRingEmblem;
|
||||||
import mage.game.events.*;
|
import mage.game.events.*;
|
||||||
import mage.game.events.TableEvent.EventType;
|
import mage.game.events.TableEvent.EventType;
|
||||||
import mage.game.mulligan.Mulligan;
|
import mage.game.mulligan.Mulligan;
|
||||||
|
|
@ -563,6 +564,34 @@ public abstract class GameImpl implements Game {
|
||||||
fireEvent(GameEvent.getEvent(GameEvent.EventType.VENTURED, playerId, null, playerId));
|
fireEvent(GameEvent.getEvent(GameEvent.EventType.VENTURED, playerId, null, playerId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TheRingEmblem getOrCreateTheRing(UUID playerId) {
|
||||||
|
TheRingEmblem emblem = state
|
||||||
|
.getCommand()
|
||||||
|
.stream()
|
||||||
|
.filter(TheRingEmblem.class::isInstance)
|
||||||
|
.map(TheRingEmblem.class::cast)
|
||||||
|
.filter(commandObject -> commandObject.isControlledBy(playerId))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (emblem != null) {
|
||||||
|
return emblem;
|
||||||
|
}
|
||||||
|
TheRingEmblem newEmblem = new TheRingEmblem(playerId);
|
||||||
|
state.addCommandObject(newEmblem);
|
||||||
|
return newEmblem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void temptWithTheRing(UUID playerId) {
|
||||||
|
Player player = getPlayer(playerId);
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player.chooseRingBearer(this);
|
||||||
|
getOrCreateTheRing(playerId).addNextAbility(this);
|
||||||
|
fireEvent(GameEvent.getEvent(GameEvent.EventType.TEMPTED_BY_RING, playerId, null, playerId));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasDayNight() {
|
public boolean hasDayNight() {
|
||||||
return state.isHasDayNight();
|
return state.isHasDayNight();
|
||||||
|
|
@ -1302,6 +1331,7 @@ public abstract class GameImpl implements Game {
|
||||||
newWatchers.add(new EndStepCountWatcher());
|
newWatchers.add(new EndStepCountWatcher());
|
||||||
newWatchers.add(new CommanderPlaysCountWatcher()); // commander plays count uses in non commander games by some cards
|
newWatchers.add(new CommanderPlaysCountWatcher()); // commander plays count uses in non commander games by some cards
|
||||||
newWatchers.add(new CreaturesDiedWatcher());
|
newWatchers.add(new CreaturesDiedWatcher());
|
||||||
|
newWatchers.add(new TemptedByTheRingWatcher());
|
||||||
|
|
||||||
// runtime check - allows only GAME scope (one watcher per game)
|
// runtime check - allows only GAME scope (one watcher per game)
|
||||||
newWatchers.forEach(watcher -> {
|
newWatchers.forEach(watcher -> {
|
||||||
|
|
|
||||||
191
Mage/src/main/java/mage/game/command/emblems/TheRingEmblem.java
Normal file
191
Mage/src/main/java/mage/game/command/emblems/TheRingEmblem.java
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
package mage.game.command.emblems;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility;
|
||||||
|
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
|
||||||
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
import mage.abilities.effects.RestrictionEffect;
|
||||||
|
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||||
|
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||||
|
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||||
|
import mage.abilities.effects.common.SacrificeTargetEffect;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
import mage.filter.predicate.Predicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.command.Emblem;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
import mage.watchers.common.TemptedByTheRingWatcher;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public final class TheRingEmblem extends Emblem {
|
||||||
|
private static final FilterPermanent filter = new FilterControlledPermanent("your Ring-bearer");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(TheRingEmblemPredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TheRingEmblem(UUID controllerId) {
|
||||||
|
super();
|
||||||
|
this.setName("The Ring");
|
||||||
|
this.setExpansionSetCodeForImage("LTR");
|
||||||
|
this.setControllerId(controllerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNextAbility(Game game) {
|
||||||
|
Ability ability;
|
||||||
|
switch (TemptedByTheRingWatcher.getCount(this.getControllerId(), game)) {
|
||||||
|
case 0:
|
||||||
|
// Your Ring-bearer is legendary and can't be blocked by creatures with greater power.
|
||||||
|
ability = new SimpleStaticAbility(Zone.COMMAND, new TheRingEmblemLegendaryEffect());
|
||||||
|
ability.addEffect(new TheRingEmblemEvasionEffect());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// Whenever your Ring-bearer attacks, draw a card, then discard a card.
|
||||||
|
ability = new AttacksCreatureYouControlTriggeredAbility(
|
||||||
|
Zone.COMMAND,
|
||||||
|
new DrawDiscardControllerEffect(1, 1),
|
||||||
|
false, filter, false
|
||||||
|
).setTriggerPhrase("Whenever your Ring-bearer attacks, ");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// Whenever your Ring-bearer becomes blocked by a creature, that creature's controller sacrifices it at end of combat.
|
||||||
|
ability = new TheRingEmblemTriggeredAbility();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// Whenever your Ring-bearer deals combat damage to a player, each opponent loses 3 life.
|
||||||
|
ability = new DealsDamageToAPlayerAllTriggeredAbility(
|
||||||
|
Zone.COMMAND, new LoseLifeOpponentsEffect(3), filter, false,
|
||||||
|
SetTargetPointer.NONE, true, false
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.getAbilities().add(ability);
|
||||||
|
ability.setSourceId(this.getId());
|
||||||
|
ability.setControllerId(this.getControllerId());
|
||||||
|
game.getState().addAbility(ability, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TheRingEmblemPredicate implements Predicate<Permanent> {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Permanent input, Game game) {
|
||||||
|
return input.isRingBearer(game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TheRingEmblemLegendaryEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
|
TheRingEmblemLegendaryEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||||
|
staticText = "your Ring-bearer is legendary";
|
||||||
|
}
|
||||||
|
|
||||||
|
private TheRingEmblemLegendaryEffect(final TheRingEmblemLegendaryEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TheRingEmblemLegendaryEffect copy() {
|
||||||
|
return new TheRingEmblemLegendaryEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Permanent permanent = Optional
|
||||||
|
.ofNullable(game.getPlayer(source.getControllerId()))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(player -> player.getRingBearer(game))
|
||||||
|
.orElse(null);
|
||||||
|
if (permanent == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
permanent.addSuperType(SuperType.LEGENDARY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TheRingEmblemEvasionEffect extends RestrictionEffect {
|
||||||
|
|
||||||
|
TheRingEmblemEvasionEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield);
|
||||||
|
staticText = "and can't be blocked by creatures with greater power";
|
||||||
|
}
|
||||||
|
|
||||||
|
private TheRingEmblemEvasionEffect(final TheRingEmblemEvasionEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TheRingEmblemEvasionEffect copy() {
|
||||||
|
return new TheRingEmblemEvasionEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||||
|
return permanent.isControlledBy(source.getControllerId())
|
||||||
|
&& permanent.isRingBearer(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
|
||||||
|
return blocker.getPower().getValue() <= attacker.getPower().getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TheRingEmblemTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
TheRingEmblemTriggeredAbility() {
|
||||||
|
super(Zone.COMMAND, new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new SacrificeTargetEffect())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TheRingEmblemTriggeredAbility(final TheRingEmblemTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TheRingEmblemTriggeredAbility copy() {
|
||||||
|
return new TheRingEmblemTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.CREATURE_BLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
Permanent attacker = game.getPermanent(event.getTargetId());
|
||||||
|
Permanent blocker = game.getPermanent(event.getSourceId());
|
||||||
|
if (attacker == null
|
||||||
|
|| blocker == null
|
||||||
|
|| attacker.isControlledBy(getControllerId())
|
||||||
|
|| !attacker.isRingBearer(game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.getEffects().setTargetPointer(new FixedTarget(blocker, game));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Whenever your Ring-bearer becomes blocked by a creature, " +
|
||||||
|
"that creature's controller sacrifices it at end of combat.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -493,6 +493,7 @@ public class GameEvent implements Serializable {
|
||||||
ROOM_ENTERED,
|
ROOM_ENTERED,
|
||||||
VENTURE, VENTURED,
|
VENTURE, VENTURED,
|
||||||
DUNGEON_COMPLETED,
|
DUNGEON_COMPLETED,
|
||||||
|
TEMPTED_BY_RING, RING_BEARER_CHOSEN,
|
||||||
REMOVED_FROM_COMBAT, // targetId id of permanent removed from combat
|
REMOVED_FROM_COMBAT, // targetId id of permanent removed from combat
|
||||||
FORETOLD, // targetId id of card foretold
|
FORETOLD, // targetId id of card foretold
|
||||||
FORETELL, // targetId id of card foretell playerId id of the controller
|
FORETELL, // targetId id of card foretell playerId id of the controller
|
||||||
|
|
|
||||||
|
|
@ -419,6 +419,8 @@ public interface Permanent extends Card, Controllable {
|
||||||
|
|
||||||
boolean isManifested();
|
boolean isManifested();
|
||||||
|
|
||||||
|
boolean isRingBearer(Game game);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Permanent copy();
|
Permanent copy();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ import mage.players.Player;
|
||||||
import mage.target.TargetPlayer;
|
import mage.target.TargetPlayer;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.GameLog;
|
import mage.util.GameLog;
|
||||||
import mage.util.RandomUtil;
|
|
||||||
import mage.util.ThreadLocalStringBuilder;
|
import mage.util.ThreadLocalStringBuilder;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
@ -1813,6 +1812,12 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
this.secondSideCard = card;
|
this.secondSideCard = card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRingBearer(Game game) {
|
||||||
|
Player player = game.getPlayer(getControllerId());
|
||||||
|
return player != null && this.equals(player.getRingBearer(game));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fight(Permanent fightTarget, Ability source, Game game) {
|
public boolean fight(Permanent fightTarget, Ability source, Game game) {
|
||||||
return this.fight(fightTarget, source, game, true);
|
return this.fight(fightTarget, source, game, true);
|
||||||
|
|
|
||||||
|
|
@ -1080,6 +1080,12 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
*/
|
*/
|
||||||
FilterMana getPhyrexianColors();
|
FilterMana getPhyrexianColors();
|
||||||
|
|
||||||
|
UUID getRingBearerId();
|
||||||
|
|
||||||
|
Permanent getRingBearer(Game game);
|
||||||
|
|
||||||
|
void chooseRingBearer(Game game);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to query if the player has strictChooseMode enabled. Only the test player can have it.
|
* Function to query if the player has strictChooseMode enabled. Only the test player can have it.
|
||||||
* Function is added here so that the test suite project does not have to be imported into the client/server project.
|
* Function is added here so that the test suite project does not have to be imported into the client/server project.
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ import mage.target.TargetAmount;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetCardInLibrary;
|
import mage.target.common.TargetCardInLibrary;
|
||||||
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
import mage.target.common.TargetDiscard;
|
import mage.target.common.TargetDiscard;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.GameLog;
|
import mage.util.GameLog;
|
||||||
|
|
@ -176,6 +177,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
// mana colors the player can handle like Phyrexian mana
|
// mana colors the player can handle like Phyrexian mana
|
||||||
protected FilterMana phyrexianColors;
|
protected FilterMana phyrexianColors;
|
||||||
|
|
||||||
|
protected UUID ringBearerId = null;
|
||||||
|
|
||||||
// Used during available mana calculation to give back possible available net mana from triggered mana abilities (No need to copy)
|
// Used during available mana calculation to give back possible available net mana from triggered mana abilities (No need to copy)
|
||||||
protected final List<List<Mana>> availableTriggeredManaList = new ArrayList<>();
|
protected final List<List<Mana>> availableTriggeredManaList = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -285,6 +288,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
this.payManaMode = player.payManaMode;
|
this.payManaMode = player.payManaMode;
|
||||||
this.phyrexianColors = player.getPhyrexianColors() != null ? player.phyrexianColors.copy() : null;
|
this.phyrexianColors = player.getPhyrexianColors() != null ? player.phyrexianColors.copy() : null;
|
||||||
|
this.ringBearerId = player.ringBearerId;
|
||||||
for (Designation object : player.designations) {
|
for (Designation object : player.designations) {
|
||||||
this.designations.add(object.copy());
|
this.designations.add(object.copy());
|
||||||
}
|
}
|
||||||
|
|
@ -372,6 +376,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
this.phyrexianColors = player.getPhyrexianColors() != null ? player.getPhyrexianColors().copy() : null;
|
this.phyrexianColors = player.getPhyrexianColors() != null ? player.getPhyrexianColors().copy() : null;
|
||||||
|
|
||||||
|
this.ringBearerId = player.getRingBearerId();
|
||||||
|
|
||||||
this.designations.clear();
|
this.designations.clear();
|
||||||
for (Designation object : player.getDesignations()) {
|
for (Designation object : player.getDesignations()) {
|
||||||
this.designations.add(object.copy());
|
this.designations.add(object.copy());
|
||||||
|
|
@ -5127,6 +5133,62 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
return this.phyrexianColors;
|
return this.phyrexianColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getRingBearerId() {
|
||||||
|
return ringBearerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Permanent getRingBearer(Game game) {
|
||||||
|
if (ringBearerId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Permanent bearer = game.getPermanent(ringBearerId);
|
||||||
|
if (bearer != null && bearer.isControlledBy(getId())) {
|
||||||
|
return bearer;
|
||||||
|
}
|
||||||
|
ringBearerId = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chooseRingBearer(Game game) {
|
||||||
|
Permanent currentBearer = getRingBearer(game);
|
||||||
|
int creatureCount = game.getBattlefield().count(
|
||||||
|
StaticFilters.FILTER_CONTROLLED_CREATURE, getId(), null, game
|
||||||
|
);
|
||||||
|
boolean mustChoose;
|
||||||
|
if (currentBearer == null) {
|
||||||
|
if (creatureCount > 0) {
|
||||||
|
mustChoose = true;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (currentBearer.isCreature(game)) {
|
||||||
|
if (creatureCount > 1) {
|
||||||
|
mustChoose = false;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (creatureCount > 0) {
|
||||||
|
mustChoose = false;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mustChoose && !chooseUse(Outcome.Neutral, "Choose a new Ring-bearer?", null, game)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TargetPermanent target = new TargetControlledCreaturePermanent();
|
||||||
|
target.setNotTarget(true);
|
||||||
|
target.withChooseHint("to be your Ring-bearer");
|
||||||
|
choose(Outcome.Neutral, target, null, game);
|
||||||
|
UUID newBearerId = target.getFirstTarget();
|
||||||
|
if (game.getPermanent(newBearerId) != null) {
|
||||||
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.RING_BEARER_CHOSEN, newBearerId, null, getId()));
|
||||||
|
this.ringBearerId = newBearerId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivatedAbility chooseLandOrSpellAbility(Card card, Game game, boolean noMana) {
|
public ActivatedAbility chooseLandOrSpellAbility(Card card, Game game, boolean noMana) {
|
||||||
return card.getSpellAbility();
|
return card.getSpellAbility();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package mage.watchers.common;
|
||||||
|
|
||||||
|
import mage.constants.WatcherScope;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class TemptedByTheRingWatcher extends Watcher {
|
||||||
|
|
||||||
|
private final Map<UUID, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
|
public TemptedByTheRingWatcher() {
|
||||||
|
super(WatcherScope.GAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void watch(GameEvent event, Game game) {
|
||||||
|
switch (event.getType()) {
|
||||||
|
case TEMPTED_BY_RING:
|
||||||
|
map.compute(event.getPlayerId(), CardUtil::setOrIncrementValue);
|
||||||
|
return;
|
||||||
|
case BEGINNING_PHASE_PRE:
|
||||||
|
if (game.getTurnNum() == 1) {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
super.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getCount(UUID playerId, Game game) {
|
||||||
|
return game
|
||||||
|
.getState()
|
||||||
|
.getWatcher(TemptedByTheRingWatcher.class)
|
||||||
|
.map
|
||||||
|
.getOrDefault(playerId, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue