mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
[LCI] Implement Tishana's Tidebinder
This commit is contained in:
parent
651ed39837
commit
86389b81d9
4 changed files with 152 additions and 85 deletions
90
Mage.Sets/src/mage/cards/t/TishanasTidebinder.java
Normal file
90
Mage.Sets/src/mage/cards/t/TishanasTidebinder.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.LoseAllAbilitiesTargetEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.common.TargetActivatedOrTriggeredAbility;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class TishanasTidebinder extends CardImpl {
|
||||
|
||||
public TishanasTidebinder(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
|
||||
|
||||
this.subtype.add(SubType.MERFOLK);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// When Tishana's Tidebinder enters the battlefield, counter up to one target activated or triggered ability. If an ability of an artifact, creature, or planeswalker is countered this way, that permanent loses all abilities for as long as Tishana's Tidebinder remains on the battlefield.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new TishanasTidebinderEffect());
|
||||
ability.addTarget(new TargetActivatedOrTriggeredAbility(0, 1));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private TishanasTidebinder(final TishanasTidebinder card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TishanasTidebinder copy() {
|
||||
return new TishanasTidebinder(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TishanasTidebinderEffect extends OneShotEffect {
|
||||
|
||||
TishanasTidebinderEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "counter up to one target activated or triggered ability. If an ability of an " +
|
||||
"artifact, creature, or planeswalker is countered this way, that permanent loses " +
|
||||
"all abilities for as long as {this} remains on the battlefield";
|
||||
}
|
||||
|
||||
private TishanasTidebinderEffect(final TishanasTidebinderEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TishanasTidebinderEffect copy() {
|
||||
return new TishanasTidebinderEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
StackObject stackObject = game.getStack().getStackObject(getTargetPointer().getFirst(game, source));
|
||||
if (stackObject == null) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(stackObject.getSourceId());
|
||||
game.getStack().counter(stackObject.getId(), source, game);
|
||||
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || sourcePermanent == null
|
||||
|| !permanent.isArtifact(game) && !permanent.isCreature(game) && !permanent.isPlaneswalker(game)) {
|
||||
return true;
|
||||
}
|
||||
game.addEffect(new LoseAllAbilitiesTargetEffect(Duration.UntilSourceLeavesBattlefield)
|
||||
.setTargetPointer(new FixedTarget(permanent, game)), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -323,6 +323,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Threefold Thunderhulk", 265, Rarity.RARE, mage.cards.t.ThreefoldThunderhulk.class));
|
||||
cards.add(new SetCardInfo("Throne of the Grim Captain", 266, Rarity.RARE, mage.cards.t.ThroneOfTheGrimCaptain.class));
|
||||
cards.add(new SetCardInfo("Tinker's Tote", 40, Rarity.COMMON, mage.cards.t.TinkersTote.class));
|
||||
cards.add(new SetCardInfo("Tishana's Tidebinder", 81, Rarity.RARE, mage.cards.t.TishanasTidebinder.class));
|
||||
cards.add(new SetCardInfo("Tithing Blade", 128, Rarity.COMMON, mage.cards.t.TithingBlade.class));
|
||||
cards.add(new SetCardInfo("Treasure Cove", 267, Rarity.RARE, mage.cards.t.TreasureCove.class));
|
||||
cards.add(new SetCardInfo("Treasure Map", 267, Rarity.RARE, mage.cards.t.TreasureMap.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
package mage.filter.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.filter.FilterStackObject;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class FilterActivatedOrTriggeredAbility extends FilterStackObject {
|
||||
|
||||
public FilterActivatedOrTriggeredAbility() {
|
||||
this("activated or triggered ability");
|
||||
}
|
||||
|
||||
public FilterActivatedOrTriggeredAbility(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
protected FilterActivatedOrTriggeredAbility(final FilterActivatedOrTriggeredAbility filter) {
|
||||
super(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(StackObject stackObject, UUID playerId, Ability source, Game game) {
|
||||
if (!super.match(stackObject, playerId, source, game) || !(stackObject instanceof Ability)) {
|
||||
return false;
|
||||
}
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(StackObject stackObject, Game game) {
|
||||
if (!super.match(stackObject, game) || !(stackObject instanceof Ability)) {
|
||||
return false;
|
||||
}
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +1,30 @@
|
|||
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterStackObject;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.TargetObject;
|
||||
import mage.filter.common.FilterActivatedOrTriggeredAbility;
|
||||
import mage.target.TargetStackObject;
|
||||
|
||||
public class TargetActivatedOrTriggeredAbility extends TargetObject {
|
||||
public class TargetActivatedOrTriggeredAbility extends TargetStackObject {
|
||||
|
||||
protected final FilterStackObject filter;
|
||||
private static final FilterStackObject defaultFilter = new FilterActivatedOrTriggeredAbility();
|
||||
|
||||
public TargetActivatedOrTriggeredAbility() {
|
||||
this(new FilterStackObject("activated or triggered ability"));
|
||||
this(1, 1);
|
||||
}
|
||||
|
||||
public TargetActivatedOrTriggeredAbility(FilterStackObject filter) {
|
||||
this.minNumberOfTargets = 1;
|
||||
this.maxNumberOfTargets = 1;
|
||||
this.zone = Zone.STACK;
|
||||
this.targetName = filter.getMessage();
|
||||
this.filter = filter;
|
||||
this(1, 1, filter);
|
||||
}
|
||||
|
||||
public TargetActivatedOrTriggeredAbility(int minNumTargets, int maxNumTargets) {
|
||||
this(minNumTargets, maxNumTargets, defaultFilter);
|
||||
}
|
||||
|
||||
public TargetActivatedOrTriggeredAbility(int minNumTargets, int maxNumTargets, FilterStackObject filter) {
|
||||
super(minNumTargets, maxNumTargets, filter);
|
||||
}
|
||||
|
||||
protected TargetActivatedOrTriggeredAbility(final TargetActivatedOrTriggeredAbility target) {
|
||||
super(target);
|
||||
this.filter = target.filter.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
// rule 114.4. A spell or ability on the stack is an illegal target for itself.
|
||||
if (source != null && source.getId().equals(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StackObject stackObject = game.getStack().getStackObject(id);
|
||||
return isActivatedOrTriggeredAbility(stackObject) && source != null && filter.match(stackObject, source.getControllerId(), source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (isActivatedOrTriggeredAbility(stackObject)
|
||||
&& filter.match(stackObject, sourceControllerId, source, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||
return game.getStack()
|
||||
.stream()
|
||||
.anyMatch(TargetActivatedOrTriggeredAbility::isActivatedOrTriggeredAbility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
|
||||
return possibleTargets(sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
return game.getStack().stream()
|
||||
.filter(TargetActivatedOrTriggeredAbility::isActivatedOrTriggeredAbility)
|
||||
.map(stackObject -> stackObject.getStackAbility().getId())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetActivatedOrTriggeredAbility copy() {
|
||||
return new TargetActivatedOrTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
static boolean isActivatedOrTriggeredAbility(StackObject stackObject) {
|
||||
if (stackObject == null) {
|
||||
return false;
|
||||
}
|
||||
if (stackObject instanceof Ability) {
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue