mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
Implement "Promise a gift" mechanic (#12578)
* [BLB] Implement Wear Down * [BLB] Implement Valley Rally * [BLB] Implement Dawn's Truce * add initial test * [BLB] Implement Kitnap * [BLB] Implement Long River's Pull * [BLB] Implement Peerless Recycling * [BLB] Implement Into the Flood Maw * add more tests * add verify skip * remove skip * a few requested changes * [BLB] Implement Nocturnal Hunger * add test for gifting a food token * [BLB] Implement Starforged Sword * add comment to activation ket * add test for adding extra cards
This commit is contained in:
parent
0d3590e579
commit
7fe6ba9c57
16 changed files with 956 additions and 1 deletions
53
Mage.Sets/src/mage/cards/d/DawnsTruce.java
Normal file
53
Mage.Sets/src/mage/cards/d/DawnsTruce.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.AddContinuousEffectToGame;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControllerEffect;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.GiftType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class DawnsTruce extends CardImpl {
|
||||
|
||||
public DawnsTruce(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
|
||||
|
||||
// Gift a card
|
||||
this.addAbility(new GiftAbility(this, GiftType.CARD));
|
||||
|
||||
// You and permanents you control gain hexproof until end of turn. If the gift was promised, permanents you control also gain indestructible until end of turn.
|
||||
this.getSpellAbility().addEffect(new GainAbilityControllerEffect(
|
||||
HexproofAbility.getInstance(), Duration.EndOfTurn
|
||||
).setText("you"));
|
||||
this.getSpellAbility().addEffect(new GainAbilityControlledEffect(
|
||||
HexproofAbility.getInstance(), Duration.EndOfTurn
|
||||
).concatBy("and"));
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new AddContinuousEffectToGame(new GainAbilityControlledEffect(
|
||||
IndestructibleAbility.getInstance(), Duration.EndOfTurn
|
||||
)), GiftWasPromisedCondition.TRUE, "if the gift was promised, " +
|
||||
"permanents you control also gain indestructible until end of turn"
|
||||
));
|
||||
}
|
||||
|
||||
private DawnsTruce(final DawnsTruce card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DawnsTruce copy() {
|
||||
return new DawnsTruce(this);
|
||||
}
|
||||
}
|
||||
58
Mage.Sets/src/mage/cards/i/IntoTheFloodMaw.java
Normal file
58
Mage.Sets/src/mage/cards/i/IntoTheFloodMaw.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package mage.cards.i;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class IntoTheFloodMaw extends CardImpl {
|
||||
|
||||
public IntoTheFloodMaw(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
|
||||
|
||||
// Gift a tapped Fish
|
||||
this.addAbility(new GiftAbility(this, GiftType.TAPPED_FISH));
|
||||
|
||||
// Return target creature an opponent controls to its owner's hand. If the gift was promise, instead return target nonland permanent an opponent controls to its owner's hand.
|
||||
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()
|
||||
.setText("return target creature an opponent controls to its owner's hand. If the gift was promise, " +
|
||||
"instead return target nonland permanent an opponent controls to its owner's hand"));
|
||||
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent());
|
||||
this.getSpellAbility().setTargetAdjuster(IntoTheFloodMawAdjuster.instance);
|
||||
}
|
||||
|
||||
private IntoTheFloodMaw(final IntoTheFloodMaw card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntoTheFloodMaw copy() {
|
||||
return new IntoTheFloodMaw(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum IntoTheFloodMawAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (GiftWasPromisedCondition.TRUE.apply(game, ability)) {
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Mage.Sets/src/mage/cards/k/Kitnap.java
Normal file
65
Mage.Sets/src/mage/cards/k/Kitnap.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.TapEnchantedEffect;
|
||||
import mage.abilities.effects.common.continuous.ControlEnchantedEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersAttachedEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Kitnap extends CardImpl {
|
||||
|
||||
public Kitnap(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}");
|
||||
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Gift a card
|
||||
this.addAbility(new GiftAbility(this, GiftType.CARD));
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// When Kitnap enters, tap enchanted creature. If the gift wasn't promised, put three stun counters on it.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect());
|
||||
ability.addEffect(new ConditionalOneShotEffect(
|
||||
new AddCountersAttachedEffect(CounterType.STUN.createInstance(3), ""),
|
||||
GiftWasPromisedCondition.FALSE, "if the gift wasn't promised, put three stun counters on it"
|
||||
));
|
||||
this.addAbility(ability);
|
||||
|
||||
// You control enchanted creature.
|
||||
this.addAbility(new SimpleStaticAbility(new ControlEnchantedEffect()));
|
||||
}
|
||||
|
||||
private Kitnap(final Kitnap card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Kitnap copy() {
|
||||
return new Kitnap(this);
|
||||
}
|
||||
}
|
||||
56
Mage.Sets/src/mage/cards/l/LongRiversPull.java
Normal file
56
Mage.Sets/src/mage/cards/l/LongRiversPull.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
package mage.cards.l;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.effects.common.CounterTargetEffect;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class LongRiversPull extends CardImpl {
|
||||
|
||||
public LongRiversPull(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}");
|
||||
|
||||
// Gift a card
|
||||
this.addAbility(new GiftAbility(this, GiftType.CARD));
|
||||
|
||||
// Counter target creature spell. If the gift was promised, instead counter target spell.
|
||||
this.getSpellAbility().addEffect(new CounterTargetEffect()
|
||||
.setText("counter target creature spell. If the gift was promised, instead counter target spell"));
|
||||
this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_CREATURE));
|
||||
this.getSpellAbility().setTargetAdjuster(LongRiversPullAdjuster.instance);
|
||||
}
|
||||
|
||||
private LongRiversPull(final LongRiversPull card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongRiversPull copy() {
|
||||
return new LongRiversPull(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum LongRiversPullAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (GiftWasPromisedCondition.TRUE.apply(game, ability)) {
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetSpell());
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Mage.Sets/src/mage/cards/n/NocturnalHunger.java
Normal file
44
Mage.Sets/src/mage/cards/n/NocturnalHunger.java
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class NocturnalHunger extends CardImpl {
|
||||
|
||||
public NocturnalHunger(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}");
|
||||
|
||||
// Gift a Food
|
||||
this.addAbility(new GiftAbility(this, GiftType.FOOD));
|
||||
|
||||
// Destroy target creature. If the gift wasn't promised, you lose 2 life.
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new LoseLifeSourceControllerEffect(2), GiftWasPromisedCondition.FALSE,
|
||||
"if the gift wasn't promised, you lose 2 life"
|
||||
));
|
||||
}
|
||||
|
||||
private NocturnalHunger(final NocturnalHunger card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NocturnalHunger copy() {
|
||||
return new NocturnalHunger(this);
|
||||
}
|
||||
}
|
||||
57
Mage.Sets/src/mage/cards/p/PeerlessRecycling.java
Normal file
57
Mage.Sets/src/mage/cards/p/PeerlessRecycling.java
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class PeerlessRecycling extends CardImpl {
|
||||
|
||||
public PeerlessRecycling(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
|
||||
|
||||
// Gift a card
|
||||
this.addAbility(new GiftAbility(this, GiftType.CARD));
|
||||
|
||||
// Return target permanent from your graveyard to your hand. If the gift was promised, instead return two target permanent cards from your graveyard to your hand.
|
||||
this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()
|
||||
.setText("return target permanent from your graveyard to your hand. If the gift was promised, " +
|
||||
"instead return two target permanent cards from your graveyard to your hand"));
|
||||
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT));
|
||||
this.getSpellAbility().setTargetAdjuster(PeerlessRecyclingAdjuster.instance);
|
||||
}
|
||||
|
||||
private PeerlessRecycling(final PeerlessRecycling card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeerlessRecycling copy() {
|
||||
return new PeerlessRecycling(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum PeerlessRecyclingAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (GiftWasPromisedCondition.TRUE.apply(game, ability)) {
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetCardInYourGraveyard(2, StaticFilters.FILTER_CARD_PERMANENTS));
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Mage.Sets/src/mage/cards/s/StarforgedSword.java
Normal file
60
Mage.Sets/src/mage/cards/s/StarforgedSword.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAttachToTarget;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
||||
import mage.abilities.effects.common.continuous.LoseAbilityAttachedEffect;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class StarforgedSword extends CardImpl {
|
||||
|
||||
public StarforgedSword(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
|
||||
|
||||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// Gift a tapped Fish
|
||||
this.addAbility(new GiftAbility(this, GiftType.TAPPED_FISH));
|
||||
|
||||
// When Starforged Sword enters, if the gift was promised, attach Starforged Sword to target creature you control.
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new EntersBattlefieldAttachToTarget(), GiftWasPromisedCondition.TRUE,
|
||||
"When {this} enters, if the gift was promised, attach {this} to target creature you control."
|
||||
));
|
||||
|
||||
// Equipped creature gets +3/+3 and loses flying.
|
||||
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 3));
|
||||
ability.addEffect(new LoseAbilityAttachedEffect(
|
||||
FlyingAbility.getInstance(), AttachmentType.EQUIPMENT
|
||||
).setText("and loses flying"));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Equip {3}
|
||||
this.addAbility(new EquipAbility(3));
|
||||
}
|
||||
|
||||
private StarforgedSword(final StarforgedSword card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StarforgedSword copy() {
|
||||
return new StarforgedSword(this);
|
||||
}
|
||||
}
|
||||
63
Mage.Sets/src/mage/cards/v/ValleyRally.java
Normal file
63
Mage.Sets/src/mage/cards/v/ValleyRally.java
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package mage.cards.v;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.AddContinuousEffectToGame;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.GiftType;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ValleyRally extends CardImpl {
|
||||
|
||||
public ValleyRally(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
|
||||
|
||||
// Gift a Food
|
||||
this.addAbility(new GiftAbility(this, GiftType.FOOD));
|
||||
|
||||
// Creatures you control get +2/+0 until end of turn. If the gift was promised, target creature you control gains first strike until end of turn.
|
||||
this.getSpellAbility().addEffect(new BoostControlledEffect(2, 0, Duration.EndOfTurn));
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new AddContinuousEffectToGame(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance())),
|
||||
GiftWasPromisedCondition.TRUE, "If the gift was promised, target creature " +
|
||||
"you control gains first strike until end of turn"
|
||||
));
|
||||
this.getSpellAbility().setTargetAdjuster(ValleyRallyAdjuster.instance);
|
||||
}
|
||||
|
||||
private ValleyRally(final ValleyRally card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValleyRally copy() {
|
||||
return new ValleyRally(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum ValleyRallyAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (GiftWasPromisedCondition.TRUE.apply(game, ability)) {
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetControlledCreaturePermanent());
|
||||
}
|
||||
}
|
||||
}
|
||||
56
Mage.Sets/src/mage/cards/w/WearDown.java
Normal file
56
Mage.Sets/src/mage/cards/w/WearDown.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
package mage.cards.w;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.GiftType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class WearDown extends CardImpl {
|
||||
|
||||
public WearDown(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
|
||||
|
||||
// Gift a card
|
||||
this.addAbility(new GiftAbility(this, GiftType.CARD));
|
||||
|
||||
// Destroy target artifact or enchantment. If the gift was promised, instead destroy two target artifacts and/or enchantments.
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect().setText("destroy target artifact or enchantment. " +
|
||||
"If the gift was promised, instead destroy two target artifacts and/or enchantments"));
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
|
||||
this.getSpellAbility().setTargetAdjuster(WearDownAdjuster.instance);
|
||||
}
|
||||
|
||||
private WearDown(final WearDown card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WearDown copy() {
|
||||
return new WearDown(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum WearDownAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (GiftWasPromisedCondition.TRUE.apply(game, ability)) {
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetPermanent(2, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Coruscation Mage", 131, Rarity.UNCOMMON, mage.cards.c.CoruscationMage.class));
|
||||
cards.add(new SetCardInfo("Curious Forager", 169, Rarity.UNCOMMON, mage.cards.c.CuriousForager.class));
|
||||
cards.add(new SetCardInfo("Darkstar Augur", 90, Rarity.RARE, mage.cards.d.DarkstarAugur.class));
|
||||
cards.add(new SetCardInfo("Dawn's Truce", 9, Rarity.RARE, mage.cards.d.DawnsTruce.class));
|
||||
cards.add(new SetCardInfo("Diresight", 91, Rarity.COMMON, mage.cards.d.Diresight.class));
|
||||
cards.add(new SetCardInfo("Downwind Ambusher", 92, Rarity.UNCOMMON, mage.cards.d.DownwindAmbusher.class));
|
||||
cards.add(new SetCardInfo("Dreamdew Entrancer", 211, Rarity.RARE, mage.cards.d.DreamdewEntrancer.class));
|
||||
|
|
@ -92,15 +93,18 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Hugs, Grisly Guardian", 218, Rarity.MYTHIC, mage.cards.h.HugsGrislyGuardian.class));
|
||||
cards.add(new SetCardInfo("Hunter's Talent", 179, Rarity.UNCOMMON, mage.cards.h.HuntersTalent.class));
|
||||
cards.add(new SetCardInfo("Innkeeper's Talent", 180, Rarity.RARE, mage.cards.i.InnkeepersTalent.class));
|
||||
cards.add(new SetCardInfo("Into the Flood Maw", 52, Rarity.UNCOMMON, mage.cards.i.IntoTheFloodMaw.class));
|
||||
cards.add(new SetCardInfo("Iridescent Vinelasher", 99, Rarity.RARE, mage.cards.i.IridescentVinelasher.class));
|
||||
cards.add(new SetCardInfo("Island", 266, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Junkblade Bruiser", 220, Rarity.COMMON, mage.cards.j.JunkbladeBruiser.class));
|
||||
cards.add(new SetCardInfo("Kindlespark Duo", 142, Rarity.COMMON, mage.cards.k.KindlesparkDuo.class));
|
||||
cards.add(new SetCardInfo("Kitnap", 53, Rarity.RARE, mage.cards.k.Kitnap.class));
|
||||
cards.add(new SetCardInfo("Kitsa, Otterball Elite", 54, Rarity.MYTHIC, mage.cards.k.KitsaOtterballElite.class));
|
||||
cards.add(new SetCardInfo("Knightfisher", 55, Rarity.UNCOMMON, mage.cards.k.Knightfisher.class));
|
||||
cards.add(new SetCardInfo("Lifecreed Duo", 20, Rarity.COMMON, mage.cards.l.LifecreedDuo.class));
|
||||
cards.add(new SetCardInfo("Lightshell Duo", 56, Rarity.COMMON, mage.cards.l.LightshellDuo.class));
|
||||
cards.add(new SetCardInfo("Lilypad Village", 255, Rarity.UNCOMMON, mage.cards.l.LilypadVillage.class));
|
||||
cards.add(new SetCardInfo("Long River's Pull", 58, Rarity.UNCOMMON, mage.cards.l.LongRiversPull.class));
|
||||
cards.add(new SetCardInfo("Lumra, Bellow of the Woods", 183, Rarity.MYTHIC, mage.cards.l.LumraBellowOfTheWoods.class));
|
||||
cards.add(new SetCardInfo("Lunar Convocation", 223, Rarity.RARE, mage.cards.l.LunarConvocation.class));
|
||||
cards.add(new SetCardInfo("Lupinflower Village", 256, Rarity.UNCOMMON, mage.cards.l.LupinflowerVillage.class));
|
||||
|
|
@ -118,11 +122,13 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Muerra, Trash Tactician", 227, Rarity.RARE, mage.cards.m.MuerraTrashTactician.class));
|
||||
cards.add(new SetCardInfo("Nettle Guard", 23, Rarity.COMMON, mage.cards.n.NettleGuard.class));
|
||||
cards.add(new SetCardInfo("Nightwhorl Hermit", 62, Rarity.COMMON, mage.cards.n.NightwhorlHermit.class));
|
||||
cards.add(new SetCardInfo("Nocturnal Hunger", 102, Rarity.COMMON, mage.cards.n.NocturnalHunger.class));
|
||||
cards.add(new SetCardInfo("Oakhollow Village", 258, Rarity.UNCOMMON, mage.cards.o.OakhollowVillage.class));
|
||||
cards.add(new SetCardInfo("Overprotect", 185, Rarity.UNCOMMON, mage.cards.o.Overprotect.class));
|
||||
cards.add(new SetCardInfo("Patchwork Banner", 247, Rarity.UNCOMMON, mage.cards.p.PatchworkBanner.class));
|
||||
cards.add(new SetCardInfo("Pawpatch Formation", 186, Rarity.UNCOMMON, mage.cards.p.PawpatchFormation.class));
|
||||
cards.add(new SetCardInfo("Pearl of Wisdom", 64, Rarity.COMMON, mage.cards.p.PearlOfWisdom.class));
|
||||
cards.add(new SetCardInfo("Peerless Recycling", 188, Rarity.UNCOMMON, mage.cards.p.PeerlessRecycling.class));
|
||||
cards.add(new SetCardInfo("Pileated Provisioner", 25, Rarity.COMMON, mage.cards.p.PileatedProvisioner.class));
|
||||
cards.add(new SetCardInfo("Plains", 262, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS));
|
||||
cards.add(new SetCardInfo("Playful Shove", 145, Rarity.UNCOMMON, mage.cards.p.PlayfulShove.class));
|
||||
|
|
@ -149,6 +155,7 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Sinister Monolith", 113, Rarity.UNCOMMON, mage.cards.s.SinisterMonolith.class));
|
||||
cards.add(new SetCardInfo("Spellgyre", 72, Rarity.UNCOMMON, mage.cards.s.Spellgyre.class));
|
||||
cards.add(new SetCardInfo("Splash Lasher", 73, Rarity.UNCOMMON, mage.cards.s.SplashLasher.class));
|
||||
cards.add(new SetCardInfo("Starforged Sword", 249, Rarity.UNCOMMON, mage.cards.s.StarforgedSword.class));
|
||||
cards.add(new SetCardInfo("Star Charter", 33, Rarity.UNCOMMON, mage.cards.s.StarCharter.class));
|
||||
cards.add(new SetCardInfo("Stargaze", 114, Rarity.UNCOMMON, mage.cards.s.Stargaze.class));
|
||||
cards.add(new SetCardInfo("Starlit Soothsayer", 115, Rarity.COMMON, mage.cards.s.StarlitSoothsayer.class));
|
||||
|
|
@ -178,6 +185,7 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Treetop Sentries", 201, Rarity.COMMON, mage.cards.t.TreetopSentries.class));
|
||||
cards.add(new SetCardInfo("Uncharted Haven", 261, Rarity.COMMON, mage.cards.u.UnchartedHaven.class));
|
||||
cards.add(new SetCardInfo("Valley Mightcaller", 202, Rarity.RARE, mage.cards.v.ValleyMightcaller.class));
|
||||
cards.add(new SetCardInfo("Valley Rally", 159, Rarity.UNCOMMON, mage.cards.v.ValleyRally.class));
|
||||
cards.add(new SetCardInfo("Valley Rotcaller", 119, Rarity.RARE, mage.cards.v.ValleyRotcaller.class));
|
||||
cards.add(new SetCardInfo("Veteran Guardmouse", 237, Rarity.COMMON, mage.cards.v.VeteranGuardmouse.class));
|
||||
cards.add(new SetCardInfo("Vinereap Mentor", 238, Rarity.UNCOMMON, mage.cards.v.VinereapMentor.class));
|
||||
|
|
@ -185,6 +193,7 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("War Squeak", 160, Rarity.COMMON, mage.cards.w.WarSqueak.class));
|
||||
cards.add(new SetCardInfo("Warren Elder", 37, Rarity.COMMON, mage.cards.w.WarrenElder.class));
|
||||
cards.add(new SetCardInfo("Warren Warleader", 38, Rarity.MYTHIC, mage.cards.w.WarrenWarleader.class));
|
||||
cards.add(new SetCardInfo("Wear Down", 203, Rarity.UNCOMMON, mage.cards.w.WearDown.class));
|
||||
cards.add(new SetCardInfo("Whiskerquill Scribe", 161, Rarity.COMMON, mage.cards.w.WhiskerquillScribe.class));
|
||||
cards.add(new SetCardInfo("Whiskervale Forerunner", 40, Rarity.RARE, mage.cards.w.WhiskervaleForerunner.class));
|
||||
cards.add(new SetCardInfo("Zoraline, Cosmos Caller", 242, Rarity.RARE, mage.cards.z.ZoralineCosmosCaller.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class GiftTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String truce = "Dawn's Truce";
|
||||
|
||||
@Test
|
||||
public void testNoGift() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.HAND, playerA, truce);
|
||||
|
||||
setChoice(playerA, false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, truce);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertAbility(playerA, "Plains", HexproofAbility.getInstance(), true, 2);
|
||||
assertAbility(playerA, "Plains", IndestructibleAbility.getInstance(), false, 2);
|
||||
assertHandCount(playerB, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGift() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.HAND, playerA, truce);
|
||||
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, playerB.getName());
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, truce);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertAbility(playerA, "Plains", HexproofAbility.getInstance(), true, 2);
|
||||
assertAbility(playerA, "Plains", IndestructibleAbility.getInstance(), true, 2);
|
||||
assertHandCount(playerB, 1);
|
||||
}
|
||||
|
||||
private static final String kitnap = "Kitnap";
|
||||
private static final String bear = "Grizzly Bears";
|
||||
|
||||
@Test
|
||||
public void testPermanentNoGift() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerB, bear);
|
||||
addCard(Zone.HAND, playerA, kitnap);
|
||||
|
||||
setChoice(playerA, false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, kitnap, bear);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, kitnap, 1);
|
||||
assertPermanentCount(playerA, bear, 1);
|
||||
assertTapped(bear, true);
|
||||
assertCounterCount(bear, CounterType.STUN, 3);
|
||||
assertHandCount(playerB, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPermanentGift() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerB, bear);
|
||||
addCard(Zone.HAND, playerA, kitnap);
|
||||
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, playerB.getName());
|
||||
setChoice(playerA, "When");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, kitnap, bear);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, kitnap, 1);
|
||||
assertPermanentCount(playerA, bear, 1);
|
||||
assertTapped(bear, true);
|
||||
assertCounterCount(bear, CounterType.STUN, 0);
|
||||
assertHandCount(playerB, 1);
|
||||
}
|
||||
|
||||
private static final String hunger = "Nocturnal Hunger";
|
||||
|
||||
@Test
|
||||
public void testNoGiftToken() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, bear);
|
||||
addCard(Zone.HAND, playerA, hunger);
|
||||
|
||||
setChoice(playerA, false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hunger, bear);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, hunger, 1);
|
||||
assertGraveyardCount(playerB, bear, 1);
|
||||
assertPermanentCount(playerB, "Food Token", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGiftToken() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, bear);
|
||||
addCard(Zone.HAND, playerA, hunger);
|
||||
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, playerB.getName());
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hunger, bear);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, hunger, 1);
|
||||
assertGraveyardCount(playerB, bear, 1);
|
||||
assertPermanentCount(playerB, "Food Token", 1);
|
||||
}
|
||||
|
||||
private static final String rally = "Valley Rally";
|
||||
|
||||
@Test
|
||||
public void testNoGiftExtraTarget() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, bear);
|
||||
addCard(Zone.HAND, playerA, rally);
|
||||
|
||||
setChoice(playerA, false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rally);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, bear, 2 + 2, 2 + 0);
|
||||
assertAbility(playerA, bear, FirstStrikeAbility.getInstance(), false);
|
||||
assertPermanentCount(playerB, "Food Token", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGiftExtraTarget() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, bear);
|
||||
addCard(Zone.HAND, playerA, rally);
|
||||
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, playerB.getName());
|
||||
addTarget(playerA, bear);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rally);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, bear, 2 + 2, 2 + 0);
|
||||
assertAbility(playerA, bear, FirstStrikeAbility.getInstance(), true);
|
||||
assertPermanentCount(playerB, "Food Token", 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.keyword.GiftAbility;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public enum GiftWasPromisedCondition implements Condition {
|
||||
TRUE(true),
|
||||
FALSE(false);
|
||||
private final boolean flag;
|
||||
|
||||
GiftWasPromisedCondition(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return flag == CardUtil.checkSourceCostsTagExists(game, source, GiftAbility.GIFT_ACTIVATION_VALUE_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Gift was " + (flag ? "" : "not ") + "promised";
|
||||
}
|
||||
}
|
||||
175
Mage/src/main/java/mage/abilities/keyword/GiftAbility.java
Normal file
175
Mage/src/main/java/mage/abilities/keyword/GiftAbility.java
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.GiftWasPromisedCondition;
|
||||
import mage.abilities.costs.*;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.GiftType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class GiftAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
||||
|
||||
private static final String keywordText = "Gift";
|
||||
private static final String reminderText = "You may promise an opponent a gift as you cast this spell. If you do, ";
|
||||
private final String rule;
|
||||
|
||||
// this is set to null first when the player chooses to use it then set to the playerId later once the player is chosen
|
||||
public static final String GIFT_ACTIVATION_VALUE_KEY = "giftPromisedActivation";
|
||||
|
||||
protected OptionalAdditionalCost additionalCost;
|
||||
private final GiftType giftType;
|
||||
|
||||
private static String makeReminderText(GiftType giftType, boolean isPermanent) {
|
||||
return reminderText + (isPermanent ? "when it enters, " : "") + "they " +
|
||||
giftType.getDescription() + (isPermanent ? "." : " before its other effects.");
|
||||
}
|
||||
|
||||
public GiftAbility(Card card, GiftType giftType) {
|
||||
super(Zone.STACK, null);
|
||||
this.additionalCost = new OptionalAdditionalCostImpl(
|
||||
keywordText + ' ' + giftType,
|
||||
makeReminderText(giftType, card.isPermanent()),
|
||||
new PromiseGiftCost(giftType)
|
||||
);
|
||||
this.additionalCost.setRepeatable(false);
|
||||
this.giftType = giftType;
|
||||
this.rule = additionalCost.getName() + ' ' + additionalCost.getReminderText();
|
||||
this.setRuleAtTheTop(true);
|
||||
if (card.isPermanent()) {
|
||||
this.addSubAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new PromiseGiftEffect(giftType)),
|
||||
GiftWasPromisedCondition.TRUE, "When this permanent enters, " +
|
||||
"if the gift was promised, they " + giftType.getDescription() + '.'
|
||||
).setRuleVisible(false));
|
||||
} else {
|
||||
card.getSpellAbility().addEffect(new PromiseGiftEffect(giftType));
|
||||
}
|
||||
}
|
||||
|
||||
private GiftAbility(final GiftAbility ability) {
|
||||
super(ability);
|
||||
this.rule = ability.rule;
|
||||
this.additionalCost = ability.additionalCost.copy();
|
||||
this.giftType = ability.giftType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GiftAbility copy() {
|
||||
return new GiftAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOptionalAdditionalCosts(Ability ability, Game game) {
|
||||
if (!(ability instanceof SpellAbility)) {
|
||||
return;
|
||||
}
|
||||
Player player = game.getPlayer(ability.getControllerId());
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
additionalCost.reset();
|
||||
if (!additionalCost.canPay(ability, this, ability.getControllerId(), game)
|
||||
|| !player.chooseUse(Outcome.Benefit, "Promise an opponent " + giftType.getName() + '?', ability, game)) {
|
||||
return;
|
||||
}
|
||||
additionalCost.activate();
|
||||
for (Cost cost : ((Costs<Cost>) additionalCost)) {
|
||||
ability.getCosts().add(cost.copy());
|
||||
}
|
||||
ability.setCostsTag(GIFT_ACTIVATION_VALUE_KEY, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCastMessageSuffix() {
|
||||
return additionalCost.getCastSuffixMessage(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
|
||||
class PromiseGiftCost extends CostImpl {
|
||||
|
||||
PromiseGiftCost(GiftType giftType) {
|
||||
text = "Gift " + giftType.getName();
|
||||
}
|
||||
|
||||
private PromiseGiftCost(final PromiseGiftCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player == null) {
|
||||
return paid;
|
||||
}
|
||||
TargetPlayer target = new TargetOpponent();
|
||||
target.withNotTarget(true);
|
||||
player.choose(Outcome.Detriment, target, source, game);
|
||||
Player opponent = game.getPlayer(target.getFirstTarget());
|
||||
if (opponent == null) {
|
||||
return paid;
|
||||
}
|
||||
source.setCostsTag(GiftAbility.GIFT_ACTIVATION_VALUE_KEY, opponent.getId());
|
||||
paid = true;
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PromiseGiftCost copy() {
|
||||
return new PromiseGiftCost(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PromiseGiftEffect extends OneShotEffect {
|
||||
|
||||
private final GiftType giftType;
|
||||
|
||||
PromiseGiftEffect(GiftType giftType) {
|
||||
super(Outcome.Benefit);
|
||||
this.giftType = giftType;
|
||||
}
|
||||
|
||||
private PromiseGiftEffect(final PromiseGiftEffect effect) {
|
||||
super(effect);
|
||||
this.giftType = effect.giftType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PromiseGiftEffect copy() {
|
||||
return new PromiseGiftEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(CardUtil.getSourceCostsTag(
|
||||
game, source, GiftAbility.GIFT_ACTIVATION_VALUE_KEY, (UUID) null
|
||||
));
|
||||
return player != null && giftType.applyGift(player, game, source);
|
||||
}
|
||||
}
|
||||
51
Mage/src/main/java/mage/constants/GiftType.java
Normal file
51
Mage/src/main/java/mage/constants/GiftType.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package mage.constants;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.FishNoAbilityToken;
|
||||
import mage.game.permanent.token.FoodToken;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public enum GiftType {
|
||||
CARD(
|
||||
"a card", "draw a card",
|
||||
(p, g, s) -> p.drawCards(1, s, g) > 0
|
||||
),
|
||||
FOOD(
|
||||
"a Food", "create a Food token",
|
||||
(p, g, s) -> new FoodToken().putOntoBattlefield(1, g, s, p.getId())
|
||||
),
|
||||
TAPPED_FISH(
|
||||
"a tapped Fish", "create a tapped 1/1 blue Fish creature token",
|
||||
(p, g, s) -> new FishNoAbilityToken().putOntoBattlefield(1, g, s, p.getId(), true, false)
|
||||
);
|
||||
|
||||
private interface GiftResolver {
|
||||
boolean apply(Player player, Game game, Ability source);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final GiftResolver giftResolver;
|
||||
|
||||
GiftType(String name, String description, GiftResolver giftResolver) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.giftResolver = giftResolver;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean applyGift(Player player, Game game, Ability source) {
|
||||
return giftResolver.apply(player, game, source);
|
||||
}
|
||||
}
|
||||
|
|
@ -1791,7 +1791,7 @@ public final class CardUtil {
|
|||
if (value == null) {
|
||||
throw new IllegalStateException("Wrong code usage: Costs tag " + tag + " has value stored of type null but is trying to be read. Use checkSourceCostsTagExists");
|
||||
}
|
||||
if (value.getClass() != defaultValue.getClass()) {
|
||||
if (defaultValue != null && value.getClass() != defaultValue.getClass()) {
|
||||
throw new IllegalStateException("Wrong code usage: Costs tag " + tag + " has value stored of type " + value.getClass().getName() + " different from default of type " + defaultValue.getClass().getName());
|
||||
}
|
||||
return (T) value;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ Foretell|card, manaString|
|
|||
For Mirrodin!|new|
|
||||
Freerunning|manaString|
|
||||
Friends forever|instance|
|
||||
Gift|card|
|
||||
Haste|instance|
|
||||
Hexproof|instance|
|
||||
Hideaway|number|
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue