sync #2

Merged
Failure merged 12 commits from External/mage:master into master 2024-11-22 14:52:57 -08:00
224 changed files with 3553 additions and 4067 deletions

View file

@ -3,6 +3,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
@ -11,7 +12,9 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePermanentEvent;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedPermanentEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
import java.util.*;
@ -44,7 +47,7 @@ public final class AegarTheFreezingFlame extends CardImpl {
}
}
class AegarTheFreezingFlameTriggeredAbility extends TriggeredAbilityImpl {
class AegarTheFreezingFlameTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
AegarTheFreezingFlameTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
@ -62,17 +65,15 @@ class AegarTheFreezingFlameTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForOnePermanentEvent dEvent = (DamagedBatchForOnePermanentEvent) event;
int excess = dEvent.getEvents()
// all events in the batch are always relevant if triggers at all
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
if (permanent == null || !game.getOpponents(getControllerId()).contains(permanent.getControllerId())) {
return false;
}
if (getFilteredEvents((DamagedBatchForOnePermanentEvent) event, game)
.stream()
.mapToInt(DamagedEvent::getExcess)
.sum();
boolean controlledByOpponent =
game.getOpponents(getControllerId()).contains(game.getControllerId(event.getTargetId()));
if (excess < 1 || !controlledByOpponent) {
.sum() < 1) {
return false;
}
AegarTheFreezingFlameWatcher watcher = game.getState().getWatcher(AegarTheFreezingFlameWatcher.class);
@ -105,7 +106,6 @@ class AegarTheFreezingFlameWatcher extends Watcher {
if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT) {
return;
}
DamagedEvent dEvent = (DamagedEvent) event;
MageObject sourceObject = game.getObject(event.getSourceId());
if (sourceObject == null) {
return;

View file

@ -2,7 +2,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.constants.Pronoun;
import mage.abilities.common.DiesOneOrMoreCreatureTriggeredAbility;
import mage.abilities.common.DiesOneOrMoreTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.ExileAndReturnSourceEffect;
@ -44,7 +44,7 @@ public final class AjaniNacatlPariah extends CardImpl {
// Whenever one or more other Cats you control die, you may exile Ajani, then return him to the battlefield transformed under his owner's control.
this.addAbility(new TransformAbility());
this.addAbility(new DiesOneOrMoreCreatureTriggeredAbility(
this.addAbility(new DiesOneOrMoreTriggeredAbility(
new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE),
filter,
true));

View file

@ -2,7 +2,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.FirstSpellOpponentsTurnTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -46,7 +46,7 @@ public final class AlelaCunningConqueror extends CardImpl {
// Whenever one or more Faeries you control deal combat damage to a player, goad target creature that player controls.
Effect effect = new GoadTargetEffect().setText("goad target creature that player controls");
Ability ability = new DealCombatDamageControlledTriggeredAbility(Zone.BATTLEFIELD, effect, faerieFilter, SetTargetPointer.PLAYER, false);
Ability ability = new OneOrMoreCombatDamagePlayerTriggeredAbility(Zone.BATTLEFIELD, effect, faerieFilter, SetTargetPointer.PLAYER, false);
ability.addTarget(new TargetPermanent(filter));
ability.setTargetAdjuster(new DamagedPlayerControlsTargetAdjuster());

View file

@ -1,25 +1,20 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.condition.common.DeliriumCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.hint.common.CardTypesInGraveyardHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import java.util.UUID;
/**
* @author fireshoes
@ -37,14 +32,11 @@ public final class AngelOfDeliverance extends CardImpl {
// <i>Delirium</i> &mdash; Whenever Angel of Deliverance deals damage, if there are four or more card types among cards in your graveyard,
// exile target creature an opponent controls.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
new AngelOfDeliveranceDealsDamageTriggeredAbility(),
DeliriumCondition.instance,
"<i>Delirium</i> &mdash; Whenever {this} deals damage, if there are four or more card types among cards in your graveyard, exile target creature an opponent controls"
);
ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE));
Ability ability = new DealsDamageSourceTriggeredAbility(new ExileTargetEffect())
.withInterveningIf(DeliriumCondition.instance);
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addHint(CardTypesInGraveyardHint.YOU);
this.addAbility(ability);
this.addAbility(ability.setAbilityWord(AbilityWord.DELIRIUM));
}
private AngelOfDeliverance(final AngelOfDeliverance card) {
@ -56,36 +48,3 @@ public final class AngelOfDeliverance extends CardImpl {
return new AngelOfDeliverance(this);
}
}
class AngelOfDeliveranceDealsDamageTriggeredAbility extends TriggeredAbilityImpl {
public AngelOfDeliveranceDealsDamageTriggeredAbility() {
super(Zone.BATTLEFIELD, new ExileTargetEffect(), false);
}
private AngelOfDeliveranceDealsDamageTriggeredAbility(final AngelOfDeliveranceDealsDamageTriggeredAbility ability) {
super(ability);
}
@Override
public AngelOfDeliveranceDealsDamageTriggeredAbility copy() {
return new AngelOfDeliveranceDealsDamageTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER
|| event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) {
for (Effect effect : this.getEffects()) {
effect.setValue("damage", event.getAmount());
}
return true;
}
return false;
}
}

View file

@ -1,24 +1,19 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.YoureDealtDamageTriggeredAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import java.util.UUID;
@ -31,7 +26,8 @@ public final class AngelheartVial extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// Whenever you're dealt damage, you may put that many charge counters on Angelheart Vial.
this.addAbility(new AngelheartVialTriggeredAbility());
this.addAbility(new YoureDealtDamageTriggeredAbility(new AddCountersSourceEffect(
CounterType.CHARGE.createInstance(), SavedDamageValue.MANY), true));
// {2}, {tap}, Remove four charge counters from Angelheart Vial: You gain 2 life and draw a card.
Ability ability = new SimpleActivatedAbility(new GainLifeEffect(2), new GenericManaCost(2));
@ -50,63 +46,3 @@ public final class AngelheartVial extends CardImpl {
return new AngelheartVial(this);
}
}
class AngelheartVialTriggeredAbility extends TriggeredAbilityImpl {
public AngelheartVialTriggeredAbility() {
super(Zone.BATTLEFIELD, new AngelheartVialEffect(), true);
}
private AngelheartVialTriggeredAbility(final AngelheartVialTriggeredAbility ability) {
super(ability);
}
@Override
public AngelheartVialTriggeredAbility copy() {
return new AngelheartVialTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getControllerId())) {
this.getEffects().get(0).setValue("damageAmount", event.getAmount());
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you're dealt damage, you may put that many charge counters on {this}.";
}
}
class AngelheartVialEffect extends OneShotEffect {
AngelheartVialEffect() {
super(Outcome.Benefit);
}
private AngelheartVialEffect(final AngelheartVialEffect effect) {
super(effect);
}
@Override
public AngelheartVialEffect copy() {
return new AngelheartVialEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
permanent.addCounters(CounterType.CHARGE.createInstance((Integer) this.getValue("damageAmount")), source.getControllerId(), source, game);
}
return true;
}
}

View file

@ -2,7 +2,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.OneShotEffect;
@ -39,7 +39,7 @@ public final class AnowonTheRuinThief extends CardImpl {
));
// Whenever one or more Rogues you control deal combat damage to a player, that player mills a card for each 1 damage dealt to them. If the player mills at least one creature card this way, you draw a card.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(Zone.BATTLEFIELD, new AnowonTheRuinThiefEffect(),
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(Zone.BATTLEFIELD, new AnowonTheRuinThiefEffect(),
filter, SetTargetPointer.PLAYER, false));
}

View file

@ -1,10 +1,10 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
@ -21,6 +21,7 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game;
import mage.game.events.DamagedPermanentEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
@ -49,11 +50,11 @@ public final class Arcbond extends CardImpl {
}
}
class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility {
class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility implements BatchTriggeredAbility<DamagedPermanentEvent> {
MageObjectReference targetObject;
public ArcbondDelayedTriggeredAbility() {
ArcbondDelayedTriggeredAbility() {
super(new ArcbondEffect(), Duration.EndOfTurn, false);
}
@ -65,6 +66,7 @@ class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility {
@Override
public void init(Game game) {
// because target can already be gone from battlefield if triggered ability resolves, we need to hold an own object reference
// TODO: this doesn't seem like it can actually work as described, wtf
targetObject = new MageObjectReference(getTargets().getFirstTarget(), game);
if (targetObject != null) {
for (Effect effect : this.getEffects()) {
@ -91,9 +93,7 @@ class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility {
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(targetObject.getSourceId())
&& targetObject.getPermanentOrLKIBattlefield(game) != null) {
for (Effect effect : this.getEffects()) {
effect.setValue("damage", event.getAmount());
}
getEffects().setValue("damage", event.getAmount());
return true;
}
return false;

View file

@ -2,7 +2,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.PayEnergyCost;
import mage.abilities.effects.common.CreateTokenEffect;
@ -22,7 +22,7 @@ public final class AutomatedAssemblyLine extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}");
// Whenever one or more artifact creatures you control deal combat damage to a player, you get {E}.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(
new GetEnergyCountersControllerEffect(1), StaticFilters.FILTER_PERMANENTS_ARTIFACT_CREATURE));
// Pay {E}{E}{E}: Create a tapped 3/3 colorless Robot artifact creature token.

View file

@ -29,7 +29,7 @@ public final class BindingAgony extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget));
// Whenever enchanted creature is dealt damage, Binding Agony deals that much damage to that creature's controller.
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DamageAttachedControllerEffect(SavedDamageValue.MUCH), false));
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DamageAttachedControllerEffect(SavedDamageValue.MUCH)));
}
private BindingAgony(final BindingAgony card) {

View file

@ -1,42 +1,35 @@
package mage.cards.b;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SpellControlledDealsDamageTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.filter.StaticFilters;
import mage.game.permanent.token.SoldierTokenWithHaste;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class BlazeCommando extends CardImpl {
public BlazeCommando (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{W}");
public BlazeCommando(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{W}");
this.subtype.add(SubType.MINOTAUR, SubType.SOLDIER);
this.power = new MageInt(5);
this.toughness = new MageInt(3);
// Whenever an instant or sorcery spell you control deals damage, create two 1/1 red and white Soldier creature tokens with haste.
this.addAbility(new BlazeCommandoTriggeredAbility());
this.addAbility(new SpellControlledDealsDamageTriggeredAbility(Zone.BATTLEFIELD,
new CreateTokenEffect(new SoldierTokenWithHaste(), 2),
StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, false
));
}
@ -50,57 +43,3 @@ public final class BlazeCommando extends CardImpl {
}
}
class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl {
private final List<UUID> handledStackObjects = new ArrayList<>();
public BlazeCommandoTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new SoldierTokenWithHaste(), 2), false);
setTriggerPhrase("Whenever an instant or sorcery spell you control deals damage, ");
}
private BlazeCommandoTriggeredAbility(final BlazeCommandoTriggeredAbility ability) {
super(ability);
}
@Override
public BlazeCommandoTriggeredAbility copy() {
return new BlazeCommandoTriggeredAbility(this);
}
@Override
public void reset(Game game) {
/**
* Blaze Commando's ability triggers each time an instant or sorcery spell you control
* deals damage (or, put another way, the number of times the word "deals" appears in
* its instructions), no matter how much damage is dealt or how many players or permanents
* are dealt damage. For example, if you cast Punish the Enemy and it "deals 3 damage to
* target player and 3 damage to target creature," Blaze Commando's ability will trigger
* once and you'll get two Soldier tokens.
*/
handledStackObjects.clear();
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (isControlledBy(game.getControllerId(event.getSourceId()))) {
MageObject damageSource = game.getObject(event.getSourceId());
if (damageSource != null) {
if (damageSource.isInstantOrSorcery(game)) {
if (!handledStackObjects.contains(damageSource.getId())) {
handledStackObjects.add(damageSource.getId());
return true;
}
}
}
}
return false;
}
}

View file

@ -1,8 +1,10 @@
package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.common.OpponentsCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
@ -15,16 +17,14 @@ import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedBatchForPermanentsEvent;
import mage.game.events.DamagedPermanentEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
import mage.abilities.costs.mana.GenericManaCost;
import mage.target.common.TargetControlledCreaturePermanent;
/**
* @author TheElk801
@ -32,7 +32,7 @@ import mage.target.common.TargetControlledCreaturePermanent;
public final class BlazingSunsteel extends CardImpl {
public BlazingSunsteel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT }, "{1}{R}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{R}");
this.subtype.add(SubType.EQUIPMENT);
@ -40,8 +40,7 @@ public final class BlazingSunsteel extends CardImpl {
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(OpponentsCount.instance, StaticValue.get(0))
.setText("equipped creature gets +1/+0 for each opponent you have")));
// Whenever equipped creature is dealt damage, it deals that much damage to any
// target.
// Whenever equipped creature is dealt damage, it deals that much damage to any target.
this.addAbility(new BlazingSunsteelTriggeredAbility());
// Equip {4}
@ -58,7 +57,7 @@ public final class BlazingSunsteel extends CardImpl {
}
}
class BlazingSunsteelTriggeredAbility extends TriggeredAbilityImpl {
class BlazingSunsteelTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
BlazingSunsteelTriggeredAbility() {
super(Zone.BATTLEFIELD, new BlazingSunsteelEffect(), false);
@ -76,40 +75,18 @@ class BlazingSunsteelTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PERMANENTS;
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(this.getSourceId());
if (equipment == null) {
Permanent equipment = getSourcePermanentIfItStillExists(game);
if (equipment == null || !event.getTargetId().equals(equipment.getAttachedTo())) {
return false;
}
UUID attachedCreature = equipment.getAttachedTo();
if (attachedCreature == null) {
return false;
}
int damage = 0;
DamagedBatchForPermanentsEvent dEvent = (DamagedBatchForPermanentsEvent) event;
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
UUID targetID = damagedEvent.getTargetId();
if (targetID == null) {
continue;
}
if (targetID == attachedCreature) {
damage += damagedEvent.getAmount();
}
}
if (damage > 0) {
this.getEffects().setValue("equipped", attachedCreature);
this.getEffects().setValue("damage", damage);
return true;
}
return false;
this.getEffects().setValue("equipped", equipment.getAttachedTo());
this.getEffects().setValue("damage", event.getAmount());
return true;
}
@Override
@ -136,12 +113,12 @@ class BlazingSunsteelEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent creature = game.getPermanentOrLKIBattlefield((UUID) getValue("equipped"));
Integer damage = (Integer)getValue("damage");
Integer damage = (Integer) getValue("damage");
if (creature == null || damage == null || damage < 1) {
if (creature == null || damage == null || damage < 1) {
return false;
}
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
permanent.damage(damage, creature.getId(), source, game);

View file

@ -1,18 +1,16 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.YoureDealtDamageTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.RemoveAllCountersSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
@ -29,7 +27,8 @@ public final class BloodHound extends CardImpl {
this.toughness = new MageInt(1);
// Whenever you're dealt damage, you may put that many +1/+1 counters on Blood Hound.
this.addAbility(new BloodHoundTriggeredAbility());
this.addAbility(new YoureDealtDamageTriggeredAbility(new AddCountersSourceEffect(
CounterType.P1P1.createInstance(), SavedDamageValue.MANY), true));
// At the beginning of your end step, remove all +1/+1 counters from Blood Hound.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
@ -47,41 +46,3 @@ public final class BloodHound extends CardImpl {
return new BloodHound(this);
}
}
class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
BloodHoundTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true);
}
private BloodHoundTriggeredAbility(final BloodHoundTriggeredAbility ability) {
super(ability);
}
@Override
public BloodHoundTriggeredAbility copy() {
return new BloodHoundTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getControllerId()) && event.getAmount() > 0) {
this.getEffects().clear();
if (event.getAmount() > 0) {
this.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(event.getAmount())));
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you're dealt damage, you may put that many +1/+1 counters on {this}.";
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.common.DiesOneOrMoreCreaturesTriggeredAbility;
import mage.abilities.common.DiesOneOrMoreTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.condition.Condition;
@ -41,7 +41,8 @@ public final class BloodSpatterAnalysis extends CardImpl {
// Whenever one or more creatures die, mill a card and put a bloodstain counter on Blood Spatter Analysis.
// Then sacrifice it if it has five or more bloodstain counters on it.
// When you do, return target creature card from your graveyard to your hand.
ability = new DiesOneOrMoreCreaturesTriggeredAbility(new MillCardsControllerEffect(1));
ability = new DiesOneOrMoreTriggeredAbility(new MillCardsControllerEffect(1),
StaticFilters.FILTER_PERMANENT_CREATURES, false);
ability.addEffect(new AddCountersSourceEffect(CounterType.BLOODSTAIN.createInstance()).concatBy("and"));
ReflexiveTriggeredAbility returnAbility = new ReflexiveTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false);
returnAbility.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));

View file

@ -1,8 +1,8 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.common.SavedGainedLifeValue;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.FlyingAbility;
@ -10,9 +10,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.constants.TargetController;
import java.util.UUID;
@ -36,7 +34,8 @@ public final class BloodthirstyConqueror extends CardImpl {
this.addAbility(DeathtouchAbility.getInstance());
// Whenever an opponent loses life, you gain that much life.
this.addAbility(new BloodthirstyConquerorTriggeredAbility());
this.addAbility(new LoseLifeTriggeredAbility(new GainLifeEffect(SavedLifeLossValue.MUCH),
TargetController.OPPONENT, false, false));
}
private BloodthirstyConqueror(final BloodthirstyConqueror card) {
@ -48,34 +47,3 @@ public final class BloodthirstyConqueror extends CardImpl {
return new BloodthirstyConqueror(this);
}
}
class BloodthirstyConquerorTriggeredAbility extends TriggeredAbilityImpl {
BloodthirstyConquerorTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(SavedGainedLifeValue.MUCH));
this.setTriggerPhrase("Whenever an opponent loses life, ");
}
private BloodthirstyConquerorTriggeredAbility(final BloodthirstyConquerorTriggeredAbility ability) {
super(ability);
}
@Override
public BloodthirstyConquerorTriggeredAbility copy() {
return new BloodthirstyConquerorTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!game.getOpponents(getControllerId()).contains(event.getTargetId())) {
return false;
}
this.getEffects().setValue(SavedGainedLifeValue.VALUE_KEY, event.getAmount());
return true;
}
}

View file

@ -2,6 +2,7 @@ package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.MenaceAbility;
@ -10,7 +11,7 @@ import mage.cards.*;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.DamagedBatchForPlayersEvent;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -55,7 +56,7 @@ public final class BreechesBrazenPlunderer extends CardImpl {
}
}
class BreechesBrazenPlundererTriggeredAbility extends TriggeredAbilityImpl {
class BreechesBrazenPlundererTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
BreechesBrazenPlundererTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
@ -70,19 +71,24 @@ class BreechesBrazenPlundererTriggeredAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PLAYERS;
}
@Override
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!game.getOpponents(getControllerId()).contains(event.getTargetId())) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return permanent != null
&& permanent.isControlledBy(getControllerId())
&& permanent.hasSubtype(SubType.PIRATE, game);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Set<UUID> opponents = new HashSet<>();
for (DamagedEvent damagedEvent : ((DamagedBatchForPlayersEvent) event).getEvents()) {
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
if (permanent == null
|| !permanent.isControlledBy(getControllerId())
|| !permanent.hasSubtype(SubType.PIRATE, game)
|| !game.getOpponents(getControllerId()).contains(damagedEvent.getTargetId())) {
continue;
}
opponents.add(damagedEvent.getTargetId());
}
getFilteredEvents((DamagedBatchForPlayersEvent) event, game)
.stream()
.map(GameEvent::getTargetId)
.forEach(opponents::add);
if (opponents.isEmpty()) {
return false;
}

View file

@ -1,7 +1,7 @@
package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.common.DiesOneOrMoreCreaturesTriggeredAbility;
import mage.abilities.common.DiesOneOrMoreTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
@ -16,6 +16,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@ -38,7 +39,8 @@ public final class Chainsaw extends CardImpl {
this.addAbility(ability);
// Whenever one or more creatures die, put a rev counter on Chainsaw.
this.addAbility(new DiesOneOrMoreCreaturesTriggeredAbility(new AddCountersSourceEffect(CounterType.REV.createInstance())));
this.addAbility(new DiesOneOrMoreTriggeredAbility(new AddCountersSourceEffect(CounterType.REV.createInstance()),
StaticFilters.FILTER_PERMANENT_CREATURES, false));
// Equipped creature gets +X/+0, where X is the number of rev counters on Chainsaw.
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(xValue, StaticValue.get(0))));

View file

@ -1,21 +1,16 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.OpponentDealtNoncombatDamageTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePlayerEvent;
import mage.game.events.GameEvent;
import mage.constants.SubType;
import java.util.UUID;
/**
*
@ -30,8 +25,11 @@ public final class ChandrasSpitfire extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
this.addAbility(new ChandrasSpitfireAbility());
// Whenever an opponent is dealt noncombat damage, Chandras Spitfire gets +3/+0 until end of turn.
this.addAbility(new OpponentDealtNoncombatDamageTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn)));
}
private ChandrasSpitfire(final ChandrasSpitfire card) {
@ -44,36 +42,3 @@ public final class ChandrasSpitfire extends CardImpl {
}
}
class ChandrasSpitfireAbility extends TriggeredAbilityImpl {
public ChandrasSpitfireAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(3, 0, Duration.EndOfTurn), false);
}
private ChandrasSpitfireAbility(final ChandrasSpitfireAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForOnePlayerEvent dEvent = (DamagedBatchForOnePlayerEvent) event;
return !dEvent.isCombatDamage() && dEvent.getAmount() > 0 && game.getOpponents(controllerId).contains(dEvent.getTargetId());
}
@Override
public String getRule() {
return "Whenever an opponent is dealt noncombat damage, {this} gets +3/+0 until end of turn.";
}
@Override
public ChandrasSpitfireAbility copy() {
return new ChandrasSpitfireAbility(this);
}
}

View file

@ -2,8 +2,8 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.abilities.condition.common.CorruptedCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@ -11,6 +11,7 @@ import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.abilities.keyword.ToxicAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
@ -19,8 +20,8 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedBatchForPlayersEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -69,7 +70,7 @@ public final class ContaminantGrafter extends CardImpl {
}
}
class ContaminantGrafterTriggeredAbility extends TriggeredAbilityImpl {
class ContaminantGrafterTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
ContaminantGrafterTriggeredAbility() {
super(Zone.BATTLEFIELD, new ProliferateEffect(false), false);
@ -86,18 +87,19 @@ class ContaminantGrafterTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForPlayersEvent dEvent = (DamagedBatchForPlayersEvent) event;
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
if (!damagedEvent.isCombatDamage()) {
continue;
}
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
if (permanent != null && permanent.isControlledBy(getControllerId())) {
return true;
}
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!event.isCombatDamage()) {
return false;
}
return false;
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return permanent != null
&& permanent.isCreature(game)
&& permanent.isControlledBy(getControllerId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return !getFilteredEvents((DamagedBatchForPlayersEvent) event, game).isEmpty();
}
@Override

View file

@ -1,6 +1,7 @@
package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.common.SourceHasCounterCondition;
@ -23,6 +24,7 @@ import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePlayerEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TreasureToken;
@ -66,7 +68,7 @@ public final class ContestedGameBall extends CardImpl {
}
}
class ContestedGameBallTriggeredAbility extends TriggeredAbilityImpl {
class ContestedGameBallTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
ContestedGameBallTriggeredAbility() {
super(Zone.BATTLEFIELD, new ContestedGameBallEffect());

View file

@ -0,0 +1,58 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.EntersWithCountersControlledEffect;
import mage.abilities.effects.keyword.ManifestDreadEffect;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CuratorBeastie extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("colorless creatures");
static {
filter.add(ColorlessPredicate.instance);
}
public CuratorBeastie(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// Reach
this.addAbility(ReachAbility.getInstance());
// Colorless creatures you control enter with two additional +1/+1 counters on them.
this.addAbility(new SimpleStaticAbility(new EntersWithCountersControlledEffect(
filter, CounterType.P1P1.createInstance(2), false
).setText("colorless creatures you control enter with two additional +1/+1 counters on them")));
// Whenever Curator Beastie enters or attacks, manifest dread.
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new ManifestDreadEffect()));
}
private CuratorBeastie(final CuratorBeastie card) {
super(card);
}
@Override
public CuratorBeastie copy() {
return new CuratorBeastie(this);
}
}

View file

@ -1,23 +1,17 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.YoureDealtDamageTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.SoldierToken;
import mage.players.Player;
import java.util.UUID;
/**
*
@ -35,7 +29,8 @@ public final class DarienKingOfKjeldor extends CardImpl {
this.toughness = new MageInt(3);
// Whenever you're dealt damage, you may create that many 1/1 white Soldier creature tokens.
this.addAbility(new DarienKingOfKjeldorTriggeredAbility());
this.addAbility(new YoureDealtDamageTriggeredAbility(new CreateTokenEffect(
new SoldierToken(), SavedDamageValue.MANY), true));
}
private DarienKingOfKjeldor(final DarienKingOfKjeldor card) {
@ -47,64 +42,3 @@ public final class DarienKingOfKjeldor extends CardImpl {
return new DarienKingOfKjeldor(this);
}
}
class DarienKingOfKjeldorTriggeredAbility extends TriggeredAbilityImpl {
public DarienKingOfKjeldorTriggeredAbility() {
super(Zone.BATTLEFIELD, new DarienKingOfKjeldorEffect(), true);
}
private DarienKingOfKjeldorTriggeredAbility(final DarienKingOfKjeldorTriggeredAbility ability) {
super(ability);
}
@Override
public DarienKingOfKjeldorTriggeredAbility copy() {
return new DarienKingOfKjeldorTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if ((event.getTargetId().equals(this.getControllerId()))) {
this.getEffects().get(0).setValue("damageAmount", event.getAmount());
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you're dealt damage, you may create that many 1/1 white Soldier creature tokens.";
}
}
class DarienKingOfKjeldorEffect extends OneShotEffect {
DarienKingOfKjeldorEffect() {
super(Outcome.Benefit);
}
private DarienKingOfKjeldorEffect(final DarienKingOfKjeldorEffect effect) {
super(effect);
}
@Override
public DarienKingOfKjeldorEffect copy() {
return new DarienKingOfKjeldorEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int damage = (Integer) this.getValue("damageAmount");
return new CreateTokenEffect(new SoldierToken(), damage).apply(game, source);
}
return false;
}
}

View file

@ -1,16 +1,12 @@
package mage.cards.d;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealtDamageAnyTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import mage.constants.SetTargetPointer;
import mage.filter.StaticFilters;
import java.util.UUID;
@ -23,7 +19,9 @@ public final class DeathPitsOfRath extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}");
// Whenever a creature is dealt damage, destroy it. It can't be regenerated.
this.addAbility(new DeathPitsOfRathTriggeredAbility());
this.addAbility(new DealtDamageAnyTriggeredAbility(new DestroyTargetEffect(true)
.setText("destroy it. It can't be regenerated"),
StaticFilters.FILTER_PERMANENT_A_CREATURE, SetTargetPointer.PERMANENT, false));
}
private DeathPitsOfRath(final DeathPitsOfRath card) {
@ -35,39 +33,3 @@ public final class DeathPitsOfRath extends CardImpl {
return new DeathPitsOfRath(this);
}
}
class DeathPitsOfRathTriggeredAbility extends TriggeredAbilityImpl {
public DeathPitsOfRathTriggeredAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect(true));
}
private DeathPitsOfRathTriggeredAbility(final DeathPitsOfRathTriggeredAbility effect) {
super(effect);
}
@Override
public DeathPitsOfRathTriggeredAbility copy() {
return new DeathPitsOfRathTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null || !permanent.isCreature(game)) {
return false;
}
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}
@Override
public String getRule() {
return "Whenever a creature is dealt damage, destroy it. It can't be regenerated.";
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.SacrificeCost;
@ -17,9 +17,7 @@ import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetSacrifice;
import mage.target.targetpointer.TargetPointer;
import mage.watchers.common.DamagedPlayerThisCombatWatcher;
import java.util.UUID;
@ -33,7 +31,7 @@ public final class DescendantsFury extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
// Whenever one or more creatures you control deal combat damage to a player, you may sacrifice one of them. If you do, reveal cards from the top of your library until you reveal a creature card that shares a creature type with the sacrificed creature. Put that card onto the battlefield and the rest on the bottom of your library in a random order.
Ability ability = new DealCombatDamageControlledTriggeredAbility(
Ability ability = new OneOrMoreCombatDamagePlayerTriggeredAbility(
new DoIfCostPaid(
new DescendantsFuryEffect(),
new DescendantsFurySacrificeCost()

View file

@ -19,7 +19,7 @@ public final class Diresight extends CardImpl {
// Surveil 2, then draw two cards. You lose 2 life.
this.getSpellAbility().addEffect(new SurveilEffect(2, false));
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy(", then"));
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).concatBy(", then"));
this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(2));
}

View file

@ -1,7 +1,7 @@
package mage.cards.d;
import mage.MageInt;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
@ -35,7 +35,7 @@ public final class DisaTheRestless extends CardImpl {
this.addAbility(new DisaTheRestlessTriggeredAbility());
// Whenever one or more creatures you control deal combat damage to a player, create a Tarmogoyf token.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(
new CreateTokenEffect(new TarmogoyfToken())
));
}

View file

@ -1,33 +1,36 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.constants.*;
import mage.abilities.keyword.SoulbondAbility;
import mage.abilities.keyword.DoctorsCompanionAbility;
import mage.abilities.keyword.SoulbondAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePermanentEvent;
import mage.game.events.DamagedPermanentEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author jimga150
*/
public final class DonnaNoble extends CardImpl {
public DonnaNoble(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(2);
@ -59,9 +62,10 @@ public final class DonnaNoble extends CardImpl {
return new DonnaNoble(this);
}
}
// Based on DealtDamageToSourceTriggeredAbility, except this uses DamagedBatchForOnePermanentEvent,
// which batches all damage dealt at the same time on a permanent-by-permanent basis
class DonnaNobleTriggeredAbility extends TriggeredAbilityImpl {
class DonnaNobleTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
DonnaNobleTriggeredAbility() {
super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MUCH));
@ -85,10 +89,8 @@ class DonnaNobleTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForOnePermanentEvent dEvent = (DamagedBatchForOnePermanentEvent) event;
// check if the permanent is Donna or its paired card
if (!CardUtil.getEventTargets(dEvent).contains(getSourceId())){
if (!CardUtil.getEventTargets(event).contains(getSourceId())) {
Permanent paired;
Permanent permanent = game.getPermanent(getSourceId());
if (permanent != null && permanent.getPairedCard() != null) {
@ -99,12 +101,12 @@ class DonnaNobleTriggeredAbility extends TriggeredAbilityImpl {
} else {
return false;
}
if (!CardUtil.getEventTargets(dEvent).contains(paired.getId())){
if (!CardUtil.getEventTargets(event).contains(paired.getId())) {
return false;
}
}
int damage = dEvent.getAmount();
int damage = event.getAmount();
if (damage < 1) {
return false;
}

View file

@ -1,11 +1,11 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -14,20 +14,21 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class DoubtlessOne extends CardImpl {
static final FilterPermanent filter = new FilterPermanent("Clerics on the battlefield");
static {
filter.add(SubType.CLERIC.getPredicate());
}
static {
filter.add(SubType.CLERIC.getPredicate());
}
public DoubtlessOne(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.CLERIC);
this.subtype.add(SubType.AVATAR);
this.power = new MageInt(0);
@ -35,9 +36,9 @@ public final class DoubtlessOne extends CardImpl {
// Doubtless One's power and toughness are each equal to the number of Clerics on the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(new PermanentsOnBattlefieldCount(filter))));
// Whenever Doubtless One deals damage, you gain that much life.
this.addAbility(new DealsDamageGainLifeSourceTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)));
}
private DoubtlessOne(final DoubtlessOne card) {
@ -48,4 +49,4 @@ public final class DoubtlessOne extends CardImpl {
public DoubtlessOne copy() {
return new DoubtlessOne(this);
}
}
}

View file

@ -2,6 +2,7 @@ package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@ -18,9 +19,9 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeBatchEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import java.util.Objects;
import java.util.UUID;
/**
@ -56,7 +57,7 @@ public final class DourPortMage extends CardImpl {
}
}
class DourPortMageTriggeredAbility extends TriggeredAbilityImpl {
class DourPortMageTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
DourPortMageTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
@ -77,17 +78,17 @@ class DourPortMageTriggeredAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
}
@Override
public boolean checkEvent(ZoneChangeEvent event, Game game) {
if (event.getFromZone() != Zone.BATTLEFIELD || event.getToZone() == Zone.GRAVEYARD || event.getTargetId().equals(getSourceId())) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
return permanent != null && permanent.isCreature(game) && permanent.isControlledBy(getControllerId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return ((ZoneChangeBatchEvent) event)
.getEvents()
.stream()
.filter(zoneChangeEvent -> Zone.BATTLEFIELD.match(zoneChangeEvent.getFromZone()))
.filter(zoneChangeEvent -> !Zone.GRAVEYARD.match(zoneChangeEvent.getToZone()))
.map(ZoneChangeEvent::getTargetId)
.filter(uuid -> !getSourceId().equals(uuid))
.map(game::getPermanentOrLKIBattlefield)
.filter(Objects::nonNull)
.anyMatch(p -> p.isCreature(game) && p.isControlledBy(getControllerId()));
return !getFilteredEvents((ZoneChangeBatchEvent) event, game).isEmpty();
}
}

View file

@ -1,29 +1,30 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class ElHajjaj extends CardImpl {
public ElHajjaj(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Whenever El-Hajj&acirc;j deals damage, you gain that much life.
this.addAbility(new DealsDamageGainLifeSourceTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)));
}
private ElHajjaj(final ElHajjaj card) {
@ -34,4 +35,4 @@ public final class ElHajjaj extends CardImpl {
public ElHajjaj copy() {
return new ElHajjaj(this);
}
}
}

View file

@ -1,26 +1,20 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.AttacksEachCombatStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.constants.SubType;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class EmberwildeCaliph extends CardImpl {
@ -42,7 +36,7 @@ public final class EmberwildeCaliph extends CardImpl {
this.addAbility(new AttacksEachCombatStaticAbility());
// Whenever Emberwilde Caliph deals damage, you lose that much life.
this.addAbility(new EmberwildeCaliphTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new LoseLifeSourceControllerEffect(SavedDamageValue.MUCH)));
}
private EmberwildeCaliph(final EmberwildeCaliph card) {
@ -54,70 +48,3 @@ public final class EmberwildeCaliph extends CardImpl {
return new EmberwildeCaliph(this);
}
}
class EmberwildeCaliphTriggeredAbility extends TriggeredAbilityImpl {
public EmberwildeCaliphTriggeredAbility() {
super(Zone.BATTLEFIELD, new EmberwildeCaliphEffect(), false);
}
private EmberwildeCaliphTriggeredAbility(final EmberwildeCaliphTriggeredAbility ability) {
super(ability);
}
@Override
public EmberwildeCaliphTriggeredAbility copy() {
return new EmberwildeCaliphTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) {
for (Effect effect : this.getEffects()) {
effect.setValue("damage", event.getAmount());
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever {this} deals damage, you lose that much life.";
}
}
class EmberwildeCaliphEffect extends OneShotEffect {
EmberwildeCaliphEffect() {
super(Outcome.LoseLife);
}
private EmberwildeCaliphEffect(final EmberwildeCaliphEffect effect) {
super(effect);
}
@Override
public EmberwildeCaliphEffect copy() {
return new EmberwildeCaliphEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int amount = (Integer) getValue("damage");
if (amount > 0) {
controller.loseLife(amount, game, source, false);
}
return true;
}
return false;
}
}

View file

@ -2,8 +2,8 @@ package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SpellControlledDealsDamageTriggeredAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
@ -15,9 +15,7 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.filter.StaticFilters;
import java.util.UUID;
@ -37,7 +35,10 @@ public final class EmbodimentOfFlame extends CardImpl {
this.nightCard = true;
// Whenever a spell you control deals damage, put a flame counter on Embodiment of Flame.
this.addAbility(new EmbodimentOfFlameTriggeredAbility());
this.addAbility(new SpellControlledDealsDamageTriggeredAbility(Zone.BATTLEFIELD,
new AddCountersSourceEffect(CounterType.FLAME.createInstance()),
StaticFilters.FILTER_SPELL, false
));
// {1}, Remove a flame counter from Embodiment of Flame: Exile the top card of your library. You may play that card this turn.
Ability ability = new SimpleActivatedAbility(
@ -57,36 +58,3 @@ public final class EmbodimentOfFlame extends CardImpl {
return new EmbodimentOfFlame(this);
}
}
class EmbodimentOfFlameTriggeredAbility extends TriggeredAbilityImpl {
EmbodimentOfFlameTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.FLAME.createInstance()));
}
private EmbodimentOfFlameTriggeredAbility(final EmbodimentOfFlameTriggeredAbility ability) {
super(ability);
}
@Override
public EmbodimentOfFlameTriggeredAbility copy() {
return new EmbodimentOfFlameTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getSpellOrLKIStack(event.getSourceId());
return spell != null && isControlledBy(spell.getControllerId()) && spell.isInstantOrSorcery(game);
}
@Override
public String getRule() {
return "Whenever a spell you control deals damage, put a flame counter on {this}.";
}
}

View file

@ -1,30 +1,26 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.DealsDamageToAnyTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.filter.FilterPermanent;
import java.util.UUID;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author cbt33
*/
public final class EssenceSliver extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent(SubType.SLIVER, "a Sliver");
public EssenceSliver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.SLIVER);
@ -33,7 +29,10 @@ public final class EssenceSliver extends CardImpl {
this.toughness = new MageInt(3);
// Whenever a Sliver deals damage, its controller gains that much life.
this.addAbility(new EssenceSliverTriggeredAbility());
this.addAbility(new DealsDamageToAnyTriggeredAbility(Zone.BATTLEFIELD,
new GainLifeTargetEffect(SavedDamageValue.MUCH).setText("its controller gains that much life"),
filter, SetTargetPointer.PLAYER, false, false
));
}
@ -46,71 +45,3 @@ public final class EssenceSliver extends CardImpl {
return new EssenceSliver(this);
}
}
class EssenceSliverTriggeredAbility extends TriggeredAbilityImpl {
public EssenceSliverTriggeredAbility() {
super(Zone.BATTLEFIELD, new EssenceSliverEffect(), false);
setTriggerPhrase("Whenever a Sliver deals damage, ");
}
private EssenceSliverTriggeredAbility(final EssenceSliverTriggeredAbility ability) {
super(ability);
}
@Override
public EssenceSliverTriggeredAbility copy() {
return new EssenceSliverTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent sliver = game.getPermanent(event.getSourceId());
if (sliver != null
&& sliver.hasSubtype(SubType.SLIVER, game)
&& sliver.getControllerId() != null) {
for (Effect effect : this.getEffects()) {
effect.setValue("damage", event.getAmount());
effect.setTargetPointer(new FixedTarget(sliver.getControllerId()));
}
return true;
}
return false;
}
}
class EssenceSliverEffect extends OneShotEffect {
EssenceSliverEffect() {
super(Outcome.GainLife);
this.staticText = "its controller gains that much life";
}
private EssenceSliverEffect(final EssenceSliverEffect effect) {
super(effect);
}
@Override
public EssenceSliverEffect copy() {
return new EssenceSliverEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controllerOfSliver = game.getPlayer(getTargetPointer().getFirst(game, source));
if (controllerOfSliver != null) {
int amount = (Integer) getValue("damage");
if (amount > 0) {
controllerOfSliver.gainLife(amount, game, source);
}
return true;
}
return false;
}
}

View file

@ -1,10 +1,10 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
@ -12,14 +12,15 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class ExaltedAngel extends CardImpl {
public ExaltedAngel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}");
this.subtype.add(SubType.ANGEL);
this.power = new MageInt(4);
@ -27,8 +28,10 @@ public final class ExaltedAngel extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Exalted Angel deals damage, you gain that much life.
this.addAbility(new DealsDamageGainLifeSourceTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)));
// Morph {2}{W}{W}
this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{2}{W}{W}")));
}

View file

@ -1,27 +1,25 @@
package mage.cards.e;
import java.util.Set;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealtDamageAnyTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.Set;
import java.util.UUID;
/**
*
* @author kleese
*/
public final class ExpeditedInheritance extends CardImpl {
@ -30,7 +28,8 @@ public final class ExpeditedInheritance extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}{R}");
// Whenever a creature is dealt damage, its controller may exile that many cards from the top of their library. They may play those cards until the end of their next turn.
this.addAbility(new ExpeditedInheritanceTriggeredAbility(new ExpeditedInheritanceExileEffect()));
this.addAbility(new DealtDamageAnyTriggeredAbility(new ExpeditedInheritanceExileEffect(),
StaticFilters.FILTER_PERMANENT_A_CREATURE, SetTargetPointer.PLAYER, false));
}
private ExpeditedInheritance(final ExpeditedInheritance card) {
@ -43,52 +42,12 @@ public final class ExpeditedInheritance extends CardImpl {
}
}
class ExpeditedInheritanceTriggeredAbility extends TriggeredAbilityImpl {
static final String IMPULSE_DRAW_AMOUNT_KEY = "playerDamage";
static final String TRIGGERING_CREATURE_KEY = "triggeringCreature";
public ExpeditedInheritanceTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
}
private ExpeditedInheritanceTriggeredAbility(final ExpeditedInheritanceTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null || !permanent.isCreature(game)) {
return false;
}
getEffects().setValue(IMPULSE_DRAW_AMOUNT_KEY, event.getAmount());
getEffects().setValue(TRIGGERING_CREATURE_KEY, new MageObjectReference(event.getTargetId(), game));
return true;
}
@Override
public String getRule() {
return "Whenever a creature is dealt damage, its controller may exile that many cards from the top of their library. They may play those cards until the end of their next turn.";
}
@Override
public ExpeditedInheritanceTriggeredAbility copy() {
return new ExpeditedInheritanceTriggeredAbility(this);
}
}
class ExpeditedInheritanceExileEffect extends OneShotEffect {
ExpeditedInheritanceExileEffect() {
super(Outcome.Benefit);
staticText = "Exile that many cards from the top of your library. " +
"Until the end of your next turn, you may play those cards.";
staticText = "its controller may exile that many cards from the top of their library." +
" They may play those cards until the end of their next turn.";
}
private ExpeditedInheritanceExileEffect(final ExpeditedInheritanceExileEffect effect) {
@ -97,31 +56,26 @@ class ExpeditedInheritanceExileEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Integer impulseDrawAmount = (Integer) this.getValue(ExpeditedInheritanceTriggeredAbility.IMPULSE_DRAW_AMOUNT_KEY);
MageObjectReference mor = (MageObjectReference) this.getValue(ExpeditedInheritanceTriggeredAbility.TRIGGERING_CREATURE_KEY);
if (impulseDrawAmount != null && mor != null) {
Permanent creature = mor.getPermanentOrLKIBattlefield(game);
if (creature != null) {
UUID playerId = creature.getControllerId();
Player player = game.getPlayer(playerId);
String message = impulseDrawAmount > 1 ?
"Exile " + CardUtil.numberToText(impulseDrawAmount) + " cards from the top of your library. Until the end of your next turn, you may play those cards."
: "Exile the top card of your library. Until the end of your next turn, you may play that card.";
if (player != null && player.chooseUse(outcome, message, source, game)) {
Set<Card> cards = player.getLibrary().getTopCards(game, impulseDrawAmount);
if (!cards.isEmpty()) {
player.moveCards(cards, Zone.EXILED, source, game);
for (Card card:cards){
ContinuousEffect effect = new ExpeditedInheritanceMayPlayEffect(playerId);
effect.setTargetPointer(new FixedTarget(card.getId(), game));
game.addEffect(effect, source);
}
}
int amount = SavedDamageValue.MANY.calculate(game, source, this);
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
if (amount <= 0 || player == null) {
return false;
}
String message = amount > 1 ?
"Exile " + CardUtil.numberToText(amount) + " cards from the top of your library. Until the end of your next turn, you may play those cards."
: "Exile the top card of your library. Until the end of your next turn, you may play that card.";
if (player.chooseUse(outcome, message, source, game)) {
Set<Card> cards = player.getLibrary().getTopCards(game, amount);
if (!cards.isEmpty()) {
player.moveCards(cards, Zone.EXILED, source, game);
for (Card card : cards) {
ContinuousEffect effect = new ExpeditedInheritanceMayPlayEffect(player.getId());
effect.setTargetPointer(new FixedTarget(card.getId(), game));
game.addEffect(effect, source);
}
}
return true;
}
return false;
return true;
}
@Override
@ -132,8 +86,8 @@ class ExpeditedInheritanceExileEffect extends OneShotEffect {
class ExpeditedInheritanceMayPlayEffect extends AsThoughEffectImpl {
private int triggeredOnTurn = 0;
private final UUID cardOwnerId;
private int triggeredOnTurn = 0;
ExpeditedInheritanceMayPlayEffect(UUID playerId) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);

View file

@ -1,16 +1,14 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.constants.TargetController;
import java.util.UUID;
/**
* @author noxx
@ -18,12 +16,11 @@ import mage.game.events.GameEvent.EventType;
public final class ExquisiteBlood extends CardImpl {
public ExquisiteBlood(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{B}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}");
// Whenever an opponent loses life, you gain that much life.
ExquisiteBloodTriggeredAbility ability = new ExquisiteBloodTriggeredAbility();
this.addAbility(ability);
this.addAbility(new LoseLifeTriggeredAbility(new GainLifeEffect(SavedLifeLossValue.MUCH),
TargetController.OPPONENT, false, false));
}
private ExquisiteBlood(final ExquisiteBlood card) {
@ -35,39 +32,3 @@ public final class ExquisiteBlood extends CardImpl {
return new ExquisiteBlood(this);
}
}
class ExquisiteBloodTriggeredAbility extends TriggeredAbilityImpl {
public ExquisiteBloodTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
}
private ExquisiteBloodTriggeredAbility(final ExquisiteBloodTriggeredAbility ability) {
super(ability);
}
@Override
public ExquisiteBloodTriggeredAbility copy() {
return new ExquisiteBloodTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (game.getOpponents(this.controllerId).contains(event.getPlayerId())) {
this.getEffects().clear();
this.addEffect(new GainLifeEffect(event.getAmount()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever an opponent loses life, you gain that much life.";
}
}

View file

@ -0,0 +1,89 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.LoseGameTargetPlayerEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect;
import mage.abilities.keyword.FreerunningAbility;
import mage.constants.*;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.filter.common.FilterNonlandCard;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author Kr4u7
*/
public final class EzioAuditoreDaFirenze extends CardImpl {
private static final FilterNonlandCard filter = new FilterNonlandCard("assassin spells you cast");
static {
filter.add(SubType.ASSASSIN.getPredicate());
}
public EzioAuditoreDaFirenze(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ASSASSIN);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Menace
this.addAbility(new MenaceAbility(false));
// Assassin spells you cast have freerunning {B}{B}.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledSpellsEffect(new FreerunningAbility("{B}{B}"), filter)));
// Whenever Ezio deals combat damage to a player, you may pay {W}{U}{B}{R}{G} if that player has 10 or less life. When you do, that player loses the game.
this.addAbility(
new DealsCombatDamageToAPlayerTriggeredAbility(
new ConditionalOneShotEffect(new DoWhenCostPaid(
new ReflexiveTriggeredAbility(new LoseGameTargetPlayerEffect(), false, "that player loses the game."), new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), "you may pay {W}{U}{B}{R}{G} if that player has 10 or less life. When you do, that player loses the game."
), EzioAuditoreDaFirenzeCondition.instance, "you may pay {W}{U}{B}{R}{G} if that player has 10 or less life. When you do, that player loses the game"), false, true
)
);
}
private EzioAuditoreDaFirenze(final EzioAuditoreDaFirenze card) {
super(card);
}
@Override
public EzioAuditoreDaFirenze copy() {
return new EzioAuditoreDaFirenze(this);
}
}
enum EzioAuditoreDaFirenzeCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
UUID playerId = source.getEffects().get(0).getTargetPointer().getFirst(game, source);
if (playerId == null) {
return false;
}
Player player = game.getPlayer(playerId);
return player != null && player.getLife() <= 10;
}
@Override
public String toString() {
return "that player has 10 or less life";
}
}

View file

@ -2,7 +2,7 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue;
import mage.abilities.effects.common.GainLifeEffect;
@ -38,7 +38,7 @@ public final class FaerieBladecrafter extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever one or more Faeries you control deal combat damage to a player, put a +1/+1 counter on Faerie Bladecrafter.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter));
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter));
// When Faerie Bladecrafter dies, each opponent loses X life and you gain X life, where X is its power.
Ability ability = new DiesSourceTriggeredAbility(new LoseLifeOpponentsEffect(SourcePermanentPowerValue.NOT_NEGATIVE).setText("each opponent loses X life"));

View file

@ -1,6 +1,7 @@
package mage.cards.f;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -48,7 +49,7 @@ public final class FallOfCairAndros extends CardImpl {
}
}
class FallOfCairAndrosTriggeredAbility extends TriggeredAbilityImpl {
class FallOfCairAndrosTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
FallOfCairAndrosTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
@ -70,6 +71,7 @@ class FallOfCairAndrosTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
// all events in the batch are always relevant if triggers at all
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null || !permanent.isCreature(game)
|| !game.getOpponents(getControllerId()).contains(permanent.getControllerId())) {

View file

@ -2,7 +2,7 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect;
@ -65,7 +65,7 @@ public final class FelineSovereign extends CardImpl {
}
}
class FelineSovereignTriggeredAbility extends DealCombatDamageControlledTriggeredAbility {
class FelineSovereignTriggeredAbility extends OneOrMoreCombatDamagePlayerTriggeredAbility {
private static final FilterCreaturePermanent catFilter = new FilterCreaturePermanent(SubType.CAT, "Cats");

View file

@ -2,6 +2,8 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ReplacementEffectImpl;
@ -16,7 +18,6 @@ import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.events.NumberOfTriggersEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
@ -77,49 +78,38 @@ class FelixFiveBootsEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event;
Permanent sourcePermanent = game.getPermanent(numberOfTriggersEvent.getSourceId());
if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) {
// Permanent whose ability is being triggered (and will be retriggered)
Permanent triggeringPermanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
if (triggeringPermanent == null || !triggeringPermanent.isControlledBy(source.getControllerId())) {
return false;
}
GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent();
if (sourceEvent == null) {
return false;
}
GameEvent sourceEvent = ((NumberOfTriggersEvent) event).getSourceEvent();
// check all damage events and damage batch events
if (sourceEvent instanceof DamagedEvent) {
return checkDamagedEvent((DamagedEvent) sourceEvent, source.getControllerId(), game);
} else if (sourceEvent instanceof BatchEvent) {
for (Object singleEventAsObject : ((BatchEvent) sourceEvent).getEvents()) {
if (singleEventAsObject instanceof DamagedEvent
&& checkDamagedEvent((DamagedEvent) singleEventAsObject, source.getControllerId(), game)
) {
// For batch events, if one of the event inside the condition match the condition,
// the effect applies to the whole batch events.
TriggeredAbility sourceTrigger = ((NumberOfTriggersEvent) event).getSourceTrigger();
for (Object o : sourceTrigger instanceof BatchTriggeredAbility
? ((BatchTriggeredAbility<?>) sourceTrigger).getFilteredEvents((BatchEvent) sourceEvent, game)
: ((BatchEvent<?>) sourceEvent).getEvents()) {
if (o instanceof DamagedEvent && checkDamagedEvent((DamagedEvent) o, source.getControllerId(), game)) {
return true;
}
}
}
return false;
}
// Checks that a given DamagedEvent matches with
// "If a creature you control dealing combat damage to a player"
private static boolean checkDamagedEvent(DamagedEvent event, UUID controllerId, Game game) {
if (event == null) {
if (!event.isCombatDamage() || game.getPlayer(event.getTargetId()) == null) {
return false;
}
UUID sourceId = event.getSourceId();
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(sourceId);
UUID targetId = event.getTargetId();
Player playerDealtDamage = game.getPlayer(targetId);
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return sourcePermanent != null
&& sourcePermanent.isCreature(game)
&& sourcePermanent.isControlledBy(controllerId)
&& event.isCombatDamage()
&& playerDealtDamage != null;
&& sourcePermanent.isControlledBy(controllerId);
}
@Override

View file

@ -1,6 +1,6 @@
package mage.cards.f;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
@ -25,7 +25,7 @@ public final class FeywildVisitor extends CardImpl {
// Commander creatures you own have "Whenever one or more nontoken creatures you control deal combat damage to a player, you create a 1/1 blue Faerie Dragon creature token with flying."
this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
new DealCombatDamageControlledTriggeredAbility(new CreateTokenEffect(new FaerieDragonToken()), StaticFilters.FILTER_CREATURE_NON_TOKEN)
new OneOrMoreCombatDamagePlayerTriggeredAbility(new CreateTokenEffect(new FaerieDragonToken()), StaticFilters.FILTER_CREATURE_NON_TOKEN)
.setTriggerPhrase("Whenever one or more nontoken creatures you control deal combat damage to a player, you "),
Duration.WhileOnBattlefield,
StaticFilters.FILTER_CREATURES_OWNED_COMMANDER

View file

@ -1,8 +1,7 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -13,22 +12,18 @@ import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedBatchForPermanentsEvent;
import mage.game.events.DamagedPermanentEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
import java.util.UUID;
/**
*
* @author zeffirojoe
*/
public final class Fiendlash extends CardImpl {
@ -44,8 +39,7 @@ public final class Fiendlash extends CardImpl {
.setText("and has reach"));
this.addAbility(staticAbility);
// Whenever equipped creature is dealt damage, it deals damage equal to its
// power to target player or planeswalker.
// Whenever equipped creature is dealt damage, it deals damage equal to its power to target player or planeswalker.
this.addAbility(new FiendlashTriggeredAbility());
// Equip {2}{R}
@ -62,7 +56,7 @@ public final class Fiendlash extends CardImpl {
}
}
class FiendlashTriggeredAbility extends TriggeredAbilityImpl {
class FiendlashTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
FiendlashTriggeredAbility() {
super(Zone.BATTLEFIELD, new FiendlashEffect(), false);
@ -80,36 +74,17 @@ class FiendlashTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PERMANENTS;
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(this.getSourceId());
if (equipment == null) {
Permanent equipment = getSourcePermanentIfItStillExists(game);
if (equipment == null || !event.getTargetId().equals(equipment.getAttachedTo())) {
return false;
}
UUID attachedCreature = equipment.getAttachedTo();
if (attachedCreature == null) {
return false;
}
game.getState().setValue("Fiendlash" + equipment.getId(), attachedCreature);
DamagedBatchForPermanentsEvent dEvent = (DamagedBatchForPermanentsEvent) event;
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
UUID targetID = damagedEvent.getTargetId();
if (targetID == null) {
continue;
}
if (targetID == attachedCreature) {
return true;
}
}
return false;
game.getState().setValue("Fiendlash" + equipment.getId(), equipment.getAttachedTo());
return true;
}
@Override
@ -147,7 +122,7 @@ class FiendlashEffect extends OneShotEffect {
}
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null && (permanent.isPlaneswalker(game))) {
if (permanent != null) {
permanent.damage(damage, creature.getId(), source, game);
return true;
}

View file

@ -1,35 +1,32 @@
package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import java.util.UUID;
/**
*
* @author cbt33
*/
public final class FilthyCur extends CardImpl {
public FilthyCur(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Filthy Cur is dealt damage, you lose that much life.
this.addAbility(new DealtDamageLoseLifeTriggeredAbility(Zone.BATTLEFIELD, new LoseLifeSourceControllerEffect(0), false));
this.addAbility(new DealtDamageToSourceTriggeredAbility(
new LoseLifeSourceControllerEffect(SavedDamageValue.MUCH), false
));
}
@ -42,39 +39,3 @@ public final class FilthyCur extends CardImpl {
return new FilthyCur(this);
}
}
class DealtDamageLoseLifeTriggeredAbility extends TriggeredAbilityImpl {
public DealtDamageLoseLifeTriggeredAbility(Zone zone, Effect effect, boolean optional) {
super(zone, effect, optional);
}
private DealtDamageLoseLifeTriggeredAbility(final DealtDamageLoseLifeTriggeredAbility ability) {
super(ability);
}
@Override
public DealtDamageLoseLifeTriggeredAbility copy() {
return new DealtDamageLoseLifeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.sourceId)) {
this.getEffects().clear();
this.addEffect(new LoseLifeSourceControllerEffect(event.getAmount()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever {this} is dealt damage, you lose that much life.";
}
}

View file

@ -1,8 +1,7 @@
package mage.cards.f;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealsDamageToAnyTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.effects.common.DamageTargetEffect;
@ -10,33 +9,30 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.filter.StaticFilters;
import mage.target.common.TargetAnyTarget;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class FiveAlarmFire extends CardImpl {
public FiveAlarmFire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}");
// Whenever a creature you control deals combat damage, put a blaze counter on Five-Alarm Fire.
this.addAbility(new DealsDamageToAnyTriggeredAbility(Zone.BATTLEFIELD,
new AddCountersSourceEffect(CounterType.BLAZE.createInstance()),
StaticFilters.FILTER_CONTROLLED_A_CREATURE,
SetTargetPointer.NONE, true, false
));
//Whenever a creature you control deals combat damage, put a blaze counter on Five-Alarm Fire.
this.addAbility(new FiveAlarmFireTriggeredAbility());
//Remove five blaze counters from Five-Alarm Fire: Five-Alarm Fire deals 5 damage to any target.
// Remove five blaze counters from Five-Alarm Fire: Five-Alarm Fire deals 5 damage to any target.
Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(5, "it"), new RemoveCountersSourceCost(CounterType.BLAZE.createInstance(5)));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
@ -51,54 +47,3 @@ public final class FiveAlarmFire extends CardImpl {
return new FiveAlarmFire(this);
}
}
class FiveAlarmFireTriggeredAbility extends TriggeredAbilityImpl {
// Because a creature that is blocked by multiple creatures it deals damage to, only causes to add one counter to ,
// it's neccessary to remember which creature already triggered
Set<UUID> triggeringCreatures = new HashSet<>();
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
public FiveAlarmFireTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.BLAZE.createInstance()), false);
setTriggerPhrase("Whenever a creature you control deals combat damage, ");
}
private FiveAlarmFireTriggeredAbility(final FiveAlarmFireTriggeredAbility ability) {
super(ability);
triggeringCreatures.addAll(ability.triggeringCreatures);
}
@Override
public FiveAlarmFireTriggeredAbility copy() {
return new FiveAlarmFireTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER
|| event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_PRE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
if (((DamagedEvent) event).isCombatDamage() && !triggeringCreatures.contains(event.getSourceId())) {
Permanent permanent = game.getPermanent(event.getSourceId());
if (permanent != null && filter.match(permanent, controllerId, this, game)) {
triggeringCreatures.add(event.getSourceId());
return true;
}
}
}
// reset the remembered creatures for every combat damage step
if (event.getType() == GameEvent.EventType.COMBAT_DAMAGE_STEP_PRE) {
triggeringCreatures.clear();
}
return false;
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.f;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SpellControlledDealsDamageTriggeredAbility;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
@ -9,9 +9,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.filter.StaticFilters;
import java.util.UUID;
@ -31,7 +29,9 @@ public final class FlameChanneler extends CardImpl {
// When a spell you control deals damage, transform Flame Channeler.
this.addAbility(new TransformAbility());
this.addAbility(new FlameChannelerTriggeredAbility());
this.addAbility(new SpellControlledDealsDamageTriggeredAbility(Zone.BATTLEFIELD,
new TransformSourceEffect(), StaticFilters.FILTER_SPELL, false
).setTriggerPhrase("When a spell you control deals damage, "));
}
private FlameChanneler(final FlameChanneler card) {
@ -43,36 +43,3 @@ public final class FlameChanneler extends CardImpl {
return new FlameChanneler(this);
}
}
class FlameChannelerTriggeredAbility extends TriggeredAbilityImpl {
FlameChannelerTriggeredAbility() {
super(Zone.BATTLEFIELD, new TransformSourceEffect());
}
private FlameChannelerTriggeredAbility(final FlameChannelerTriggeredAbility ability) {
super(ability);
}
@Override
public FlameChannelerTriggeredAbility copy() {
return new FlameChannelerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getSpellOrLKIStack(event.getSourceId());
return spell != null && isControlledBy(spell.getControllerId()) && spell.isInstantOrSorcery(game);
}
@Override
public String getRule() {
return "When a spell you control deals damage, transform {this}.";
}
}

View file

@ -3,6 +3,9 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.hint.ValueHint;
import mage.abilities.triggers.BeginningOfPostcombatMainTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
@ -35,7 +38,7 @@ public final class FlorianVoldarenScion extends CardImpl {
// At the beginning of your postcombat main phase, look at the top X cards of your library, where X is the total amount of life your opponents lost this turn.
// Exile one of those cards and put the rest on the bottom of your library in a random order. You may play the exiled card this turn.
this.addAbility(new BeginningOfPostcombatMainTriggeredAbility(new FlorianVoldarenScionEffect(), false));
this.addAbility(new BeginningOfPostcombatMainTriggeredAbility(new FlorianVoldarenScionEffect(), false).addHint(FlorianValue.getHint()));
}
private FlorianVoldarenScion(final FlorianVoldarenScion card) {
@ -48,6 +51,35 @@ public final class FlorianVoldarenScion extends CardImpl {
}
}
enum FlorianValue implements DynamicValue {
instance;
private static final ValueHint hint = new ValueHint("Total amount of life your opponents lost this turn", instance);
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
Player controller = game.getPlayer(sourceAbility.getControllerId());
PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class);
if (controller != null && watcher != null) {
return watcher.getAllOppLifeLost(controller.getId(), game);
}
return 0;
}
@Override
public FlorianValue copy() {
return instance;
}
@Override
public String getMessage() {
return "";
}
public static ValueHint getHint() {
return hint;
}
}
class FlorianVoldarenScionEffect extends OneShotEffect {
FlorianVoldarenScionEffect() {

View file

@ -0,0 +1,84 @@
package mage.cards.f;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.ChangelingAbility;
import mage.abilities.keyword.RetraceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.token.ShapeshifterDeathtouchToken;
import mage.players.Player;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FormlessGenesis extends CardImpl {
private static final Hint hint = new ValueHint(
"Lands in your graveyard", new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_LAND)
);
public FormlessGenesis(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.KINDRED, CardType.SORCERY}, "{2}{G}");
this.subtype.add(SubType.SHAPESHIFTER);
// Changeling
this.addAbility(new ChangelingAbility());
// Create an X/X colorless Shapeshifter creature token with changeling and deathtouch, where X is the number of land cards in your graveyard.
this.getSpellAbility().addEffect(new FormlessGenesisEffect());
this.getSpellAbility().addHint(hint);
// Retrace
this.addAbility(new RetraceAbility(this));
}
private FormlessGenesis(final FormlessGenesis card) {
super(card);
}
@Override
public FormlessGenesis copy() {
return new FormlessGenesis(this);
}
}
class FormlessGenesisEffect extends OneShotEffect {
FormlessGenesisEffect() {
super(Outcome.Benefit);
staticText = "create an X/X colorless Shapeshifter creature token with changeling and deathtouch, " +
"where X is the number of land cards in your graveyard";
}
private FormlessGenesisEffect(final FormlessGenesisEffect effect) {
super(effect);
}
@Override
public FormlessGenesisEffect copy() {
return new FormlessGenesisEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int amount = Optional
.ofNullable(game.getPlayer(source.getControllerId()))
.map(Player::getGraveyard)
.map(g -> g.count(StaticFilters.FILTER_CARD_LAND, game))
.orElse(0);
return new ShapeshifterDeathtouchToken(amount).putOntoBattlefield(1, game, source);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.dynamicvalue.common.GetXValue;
import mage.abilities.effects.common.BecomesMonarchSourceEffect;
@ -13,14 +12,15 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedBatchForPlayersEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.HumanKnightToken;
import java.util.UUID;
/**
*
* @author Susucr
*/
public final class ForthEorlingas extends CardImpl {
@ -50,7 +50,7 @@ public final class ForthEorlingas extends CardImpl {
}
}
class ForthEorlingasTriggeredAbility extends DelayedTriggeredAbility {
class ForthEorlingasTriggeredAbility extends DelayedTriggeredAbility implements BatchTriggeredAbility<DamagedPlayerEvent> {
public ForthEorlingasTriggeredAbility() {
super(new BecomesMonarchSourceEffect(), Duration.EndOfTurn, false);
@ -68,18 +68,19 @@ class ForthEorlingasTriggeredAbility extends DelayedTriggeredAbility {
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForPlayersEvent dEvent = (DamagedBatchForPlayersEvent) event;
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
if (!damagedEvent.isCombatDamage()) {
continue;
}
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
if (permanent != null && permanent.isControlledBy(getControllerId())) {
return true;
}
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!event.isCombatDamage()) {
return false;
}
return false;
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return permanent != null
&& permanent.isCreature(game)
&& permanent.isControlledBy(getControllerId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return !getFilteredEvents((DamagedBatchForPlayersEvent) event, game).isEmpty();
}
@Override

View file

@ -2,7 +2,7 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.common.CantBlockAbility;
import mage.abilities.common.OneOrMoreDealDamageTriggeredAbility;
import mage.abilities.common.OneOrMoreDamagePlayerTriggeredAbility;
import mage.abilities.effects.keyword.ExploreSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.PartnerAbility;
@ -38,7 +38,7 @@ public final class FranciscoFowlMarauder extends CardImpl {
this.addAbility(new CantBlockAbility());
// Whenever one or more Pirates you control deal damage to a player, Francisco explores.
this.addAbility(new OneOrMoreDealDamageTriggeredAbility(
this.addAbility(new OneOrMoreDamagePlayerTriggeredAbility(
new ExploreSourceEffect(false, "{this}"),
filter, false, true
));

View file

@ -3,6 +3,7 @@ package mage.cards.f;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -64,7 +65,7 @@ public final class FranticScapegoat extends CardImpl {
}
//Based on Lightmine Field
class FranticScapegoatTriggeredAbility extends TriggeredAbilityImpl {
class FranticScapegoatTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
FranticScapegoatTriggeredAbility() {
super(Zone.BATTLEFIELD, new FranticScapegoatSuspectEffect(), true);
@ -82,18 +83,24 @@ class FranticScapegoatTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkInterveningIfClause(Game game) {
Permanent source = getSourcePermanentIfItStillExists(game);
return (source != null && source.isSuspected());
return source != null && source.isSuspected();
}
@Override
public boolean checkEvent(ZoneChangeEvent event, Game game) {
if (event.getToZone() != Zone.BATTLEFIELD) {
return false;
}
Permanent permanent = event.getTarget();
return permanent != null && permanent.isCreature(game) && permanent.isControlledBy(getControllerId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeBatchEvent zEvent = (ZoneChangeBatchEvent) event;
Set<MageObjectReference> enteringCreatures = zEvent.getEvents().stream()
.filter(z -> z.getToZone() == Zone.BATTLEFIELD)
.filter(z -> this.controllerId.equals(z.getPlayerId()))
Set<MageObjectReference> enteringCreatures = getFilteredEvents((ZoneChangeBatchEvent) event, game)
.stream()
.map(ZoneChangeEvent::getTarget)
.filter(Objects::nonNull)
.filter(permanent -> permanent.isCreature(game))
.map(p -> new MageObjectReference(p, game))
.collect(Collectors.toSet());
if (!enteringCreatures.isEmpty()) {

View file

@ -14,7 +14,6 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
@ -37,7 +36,7 @@ public final class FrozenSolid extends CardImpl {
// Enchanted creature doesn't untap during its controller's untap step.
this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepEnchantedEffect()));
// When enchanted creature is dealt damage, destroy it.
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DestroyAttachedToEffect("it"), false)
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DestroyAttachedToEffect("it"))
.setTriggerPhrase("When enchanted creature is dealt damage, "));
}

View file

@ -1,15 +1,15 @@
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.effects.common.continuous.BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
@ -22,8 +22,9 @@ import mage.game.permanent.token.TokenImpl;
import mage.target.TargetPermanent;
import mage.target.common.TargetLandPermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class GenjuOfTheFields extends CardImpl {
@ -31,7 +32,7 @@ public final class GenjuOfTheFields extends CardImpl {
private static final FilterLandPermanent FILTER = new FilterLandPermanent(SubType.PLAINS, "Plains");
public GenjuOfTheFields(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}");
this.subtype.add(SubType.AURA);
// Enchant Plains
@ -45,7 +46,7 @@ public final class GenjuOfTheFields extends CardImpl {
Effect effect = new BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(new SpiritToken(),
"Until end of turn, enchanted Plains becomes a 2/5 white Spirit creature", Duration.EndOfTurn);
Ability ability2 = new SimpleActivatedAbility(effect, new GenericManaCost(2));
effect = new GainAbilityAttachedEffect(new DealsDamageGainLifeSourceTriggeredAbility(), AttachmentType.AURA, Duration.EndOfTurn);
effect = new GainAbilityAttachedEffect(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)), AttachmentType.AURA, Duration.EndOfTurn);
effect.setText("with \"Whenever this creature deals damage, its controller gains that much life.\" It's still a land");
ability2.addEffect(effect);
this.addAbility(ability2);
@ -76,6 +77,7 @@ public final class GenjuOfTheFields extends CardImpl {
power = new MageInt(2);
toughness = new MageInt(5);
}
private SpiritToken(final SpiritToken token) {
super(token);
}

View file

@ -0,0 +1,66 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.effects.keyword.ManifestDreadEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.card.FaceDownPredicate;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class GlitchInterpreter extends CardImpl {
private static final FilterPermanent filter = new FilterControlledPermanent("you control no face-down permanents");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("colorless creatures");
static {
filter.add(FaceDownPredicate.instance);
filter2.add(ColorlessPredicate.instance);
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0);
public GlitchInterpreter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// When Glitch Interpreter enters, if you control no face-down permanents, return Glitch Interpreter to its owner's hand and manifest dread.
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandSourceEffect())
.withRuleTextReplacement(false).withInterveningIf(condition);
ability.addEffect(new ManifestDreadEffect().concatBy("and"));
this.addAbility(ability);
// Whenever one or more colorless creatures you control deal combat damage to a player, draw a card.
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), filter2));
}
private GlitchInterpreter(final GlitchInterpreter card) {
super(card);
}
@Override
public GlitchInterpreter copy() {
return new GlitchInterpreter(this);
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
@ -36,7 +36,7 @@ public final class GontiCannyAcquisitor extends CardImpl {
this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)));
// Whenever one or more creatures you control deal combat damage to a player, look at the top card of that player's library, then exile it face down. You may play that card for as long as it remains exiled, and mana of any type can be spent to cast that spell.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(
new ExileFaceDownTopNLibraryYouMayPlayAsLongAsExiledTargetEffect(false, CastManaAdjustment.AS_THOUGH_ANY_MANA_TYPE)
.setText("look at the top card of that player's library, then exile it face down. "
+ "You may play that card for as long as it remains exiled, and mana of any type can be spent to cast that spell"),

View file

@ -1,7 +1,7 @@
package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.LoseLifeFirstTimeEachTurnTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.PayEnergyCost;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -10,14 +10,7 @@ import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.watchers.Watcher;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
@ -29,8 +22,8 @@ public final class GontisMachinations extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}");
// Whenever you lose life for the first time each turn, you get {E}.
this.addAbility(new GontisMachinationsTriggeredAbility(),
new GontisMachinationsFirstLostLifeThisTurnWatcher());
this.addAbility(new LoseLifeFirstTimeEachTurnTriggeredAbility(
new GetEnergyCountersControllerEffect(1)));
// Pay {E}{E}, Sacrifice Gonti's Machinations: Each opponent loses 3 life. You gain life equal to the life lost this way.
Ability ability = new SimpleActivatedAbility(
@ -50,68 +43,3 @@ public final class GontisMachinations extends CardImpl {
return new GontisMachinations(this);
}
}
class GontisMachinationsTriggeredAbility extends TriggeredAbilityImpl {
public GontisMachinationsTriggeredAbility() {
super(Zone.BATTLEFIELD, new GetEnergyCountersControllerEffect(1), false);
setTriggerPhrase("Whenever you lose life for the first time each turn, ");
}
private GontisMachinationsTriggeredAbility(final GontisMachinationsTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(getControllerId())) {
GontisMachinationsFirstLostLifeThisTurnWatcher watcher
= game.getState().getWatcher(GontisMachinationsFirstLostLifeThisTurnWatcher.class);
if (watcher != null
&& watcher.timesLostLifeThisTurn(event.getPlayerId()) < 2) {
return true;
}
}
return false;
}
@Override
public GontisMachinationsTriggeredAbility copy() {
return new GontisMachinationsTriggeredAbility(this);
}
}
class GontisMachinationsFirstLostLifeThisTurnWatcher extends Watcher {
private final Map<UUID, Integer> playersLostLife = new HashMap<>();
public GontisMachinationsFirstLostLifeThisTurnWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
switch (event.getType()) {
case LOST_LIFE:
int timesLifeLost = playersLostLife.getOrDefault(event.getPlayerId(), 0);
timesLifeLost++;
playersLostLife.put(event.getPlayerId(), timesLifeLost);
}
}
@Override
public void reset() {
super.reset();
playersLostLife.clear();
}
public int timesLostLifeThisTurn(UUID playerId) {
return playersLostLife.getOrDefault(playerId, 0);
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.g;
import mage.MageInt;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
@ -40,7 +40,7 @@ public final class GoroGoroAndSatoru extends CardImpl {
// Whenever one or more creatures you control that entered the battlefield this turn deal combat damage to a
// player, create a 5/5 red Dragon Spirit creature token with flying.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(
new CreateTokenEffect(new DragonSpiritToken()), filter
));

View file

@ -2,7 +2,7 @@ package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.ExileThenReturnTargetEffect;
@ -59,7 +59,7 @@ public final class GossipsTalent extends CardImpl {
// Whenever a creature you control deals combat damage to a player, you may exile it, then return it to the battlefield under its owner's control.
this.addAbility(new SimpleStaticAbility(new GainClassAbilitySourceEffect(
new DealCombatDamageControlledTriggeredAbility(
new OneOrMoreCombatDamagePlayerTriggeredAbility(
Zone.BATTLEFIELD,
new ExileThenReturnTargetEffect(false, false)
.setText("exile it, then return it to the battlefield under its owner's control"),

View file

@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesBlockedAllTriggeredAbility;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.constants.SubType;
@ -40,7 +40,7 @@ public final class GrazilaxxIllithidScholar extends CardImpl {
));
// Whenever one or more creatures you control deal combat damage to a player, draw a card.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new DrawCardSourceControllerEffect(1)));
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1)));
}
private GrazilaxxIllithidScholar(final GrazilaxxIllithidScholar card) {

View file

@ -1,5 +1,6 @@
package mage.cards.g;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
@ -10,6 +11,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPlayer;
@ -52,7 +54,7 @@ public final class GrievousWound extends CardImpl {
}
}
class GrievousWoundTriggeredAbility extends TriggeredAbilityImpl {
class GrievousWoundTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
GrievousWoundTriggeredAbility() {
super(Zone.BATTLEFIELD, new LoseHalfLifeTargetEffect().setText("they lose half their life, rounded up"));

View file

@ -3,7 +3,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.costs.common.SacrificeXTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.GetXValue;
@ -39,7 +39,7 @@ public final class GrimHireling extends CardImpl {
this.toughness = new MageInt(2);
// Whenever one or more creatures you control deal combat damage to a player, create two Treasure tokens.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(
new CreateTokenEffect(new TreasureToken(), 2)
));

View file

@ -1,6 +1,7 @@
package mage.cards.h;
import mage.MageInt;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.MillCardsControllerEffect;
@ -55,7 +56,7 @@ public final class HedgeShredder extends CardImpl {
}
}
class HedgeShredderTriggeredAbility extends TriggeredAbilityImpl {
class HedgeShredderTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
HedgeShredderTriggeredAbility() {
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(true));
@ -75,17 +76,22 @@ class HedgeShredderTriggeredAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
}
@Override
public boolean checkEvent(ZoneChangeEvent event, Game game) {
if (event.getFromZone() != Zone.LIBRARY || event.getToZone() != Zone.GRAVEYARD) {
return false;
}
Card card = game.getCard(event.getTargetId());
return card != null && card.isLand(game) && card.isOwnedBy(getControllerId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Set<Card> set = ((ZoneChangeBatchEvent) event).getEvents()
Set<Card> set = getFilteredEvents((ZoneChangeBatchEvent) event, game)
.stream()
.filter(e -> isControlledBy(e.getPlayerId()))
.filter(e -> e.getFromZone().match(Zone.LIBRARY))
.filter(e -> e.getToZone().match(Zone.GRAVEYARD))
.map(ZoneChangeEvent::getTargetId)
.map(game::getCard)
.filter(Objects::nonNull)
.filter(card -> card.isLand(game))
.collect(Collectors.toSet());
if (set.isEmpty()) {
return false;

View file

@ -1,6 +1,7 @@
package mage.cards.h;
import mage.MageInt;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
@ -15,8 +16,8 @@ import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedBatchForPlayersEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -61,7 +62,7 @@ public final class HordewingSkaab extends CardImpl {
}
}
class HordewingSkaabTriggeredAbility extends TriggeredAbilityImpl {
class HordewingSkaabTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
HordewingSkaabTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
@ -77,23 +78,24 @@ class HordewingSkaabTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForPlayersEvent dEvent = (DamagedBatchForPlayersEvent) event;
Set<UUID> opponents = new HashSet<>();
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
if (!damagedEvent.isCombatDamage()) {
continue;
}
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
if (permanent == null
|| !permanent.isControlledBy(getControllerId())
|| !permanent.hasSubtype(SubType.ZOMBIE, game)
|| !game.getOpponents(getControllerId()).contains(damagedEvent.getTargetId())) {
continue;
}
opponents.add(damagedEvent.getTargetId());
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!event.isCombatDamage() || !game.getOpponents(getControllerId()).contains(event.getTargetId())) {
return false;
}
if (opponents.size() < 1) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return permanent != null
&& permanent.isControlledBy(getControllerId())
&& permanent.hasSubtype(SubType.ZOMBIE, game);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Set<UUID> opponents = new HashSet<>();
getFilteredEvents((DamagedBatchForPlayersEvent) event, game)
.stream()
.map(GameEvent::getTargetId)
.forEach(opponents::add);
if (opponents.isEmpty()) {
return false;
}
this.getEffects().clear();

View file

@ -1,28 +1,29 @@
package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class HornedCheetah extends CardImpl {
public HornedCheetah(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}");
this.subtype.add(SubType.CAT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Horned Cheetah deals damage, you gain that much life.
this.addAbility(new DealsDamageGainLifeSourceTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)));
}
private HornedCheetah(final HornedCheetah card) {

View file

@ -1,8 +1,6 @@
package mage.cards.h;
import java.util.Objects;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealtDamageAttachedTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DestroyTargetEffect;
@ -10,32 +8,28 @@ import mage.abilities.effects.common.combat.CantBeBlockedAttachedEffect;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import mage.constants.*;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class HotSoup extends CardImpl {
public HotSoup(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
this.subtype.add(SubType.EQUIPMENT);
// Equipped creature can't be blocked.
this.addAbility(new SimpleStaticAbility(new CantBeBlockedAttachedEffect(AttachmentType.EQUIPMENT)));
// Whenever equipped creature is dealt damage, destroy it.
this.addAbility(new HotSoupTriggeredAbility());
this.addAbility(new DealtDamageAttachedTriggeredAbility(
Zone.BATTLEFIELD, new DestroyTargetEffect().setText("destroy it"),
false, SetTargetPointer.PERMANENT
).setTriggerPhrase("Whenever equipped creature is dealt damage, "));
// Equip {3}
this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3)));
}
@ -49,37 +43,3 @@ public final class HotSoup extends CardImpl {
return new HotSoup(this);
}
}
class HotSoupTriggeredAbility extends TriggeredAbilityImpl {
HotSoupTriggeredAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect().setText("destroy it"), false);
setTriggerPhrase("Whenever equipped creature is dealt damage, ");
}
private HotSoupTriggeredAbility(final HotSoupTriggeredAbility ability) {
super(ability);
}
@Override
public HotSoupTriggeredAbility copy() {
return new HotSoupTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(this.getSourceId());
if (equipment != null && equipment.getAttachedTo() != null) {
if (Objects.equals(event.getTargetId(), equipment.getAttachedTo())) {
this.getEffects().setTargetPointer(new FixedTarget(equipment.getAttachedTo(), game));
return true;
}
}
return false;
}
}

View file

@ -1,7 +1,8 @@
package mage.cards.h;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.Ability;
import mage.abilities.common.DealtDamageAnyTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
@ -12,11 +13,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedBatchForPermanentsEvent;
import mage.game.events.GameEvent;
import mage.filter.StaticFilters;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
@ -36,7 +35,10 @@ public final class HowlpackAvenger extends CardImpl {
this.nightCard = true;
// Whenever a permanent you control is dealt damage, Howlpack Avenger deals that much damage to any target.
this.addAbility(new HowlpackAvengerTriggeredAbility());
Ability ability = new DealtDamageAnyTriggeredAbility(new DamageTargetEffect(SavedDamageValue.MUCH),
StaticFilters.FILTER_CONTROLLED_A_PERMANENT, SetTargetPointer.NONE, false);
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
// {1}{R}: Howlpack Avenger gets +2/+0 until end of turn.
this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(
@ -56,41 +58,3 @@ public final class HowlpackAvenger extends CardImpl {
return new HowlpackAvenger(this);
}
}
class HowlpackAvengerTriggeredAbility extends TriggeredAbilityImpl {
HowlpackAvengerTriggeredAbility() {
super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MUCH));
this.addTarget(new TargetAnyTarget());
setTriggerPhrase("Whenever a permanent you control is dealt damage, ");
}
private HowlpackAvengerTriggeredAbility(final HowlpackAvengerTriggeredAbility ability) {
super(ability);
}
@Override
public HowlpackAvengerTriggeredAbility copy() {
return new HowlpackAvengerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PERMANENTS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
int damage = ((DamagedBatchForPermanentsEvent) event)
.getEvents()
.stream()
.filter(damagedEvent -> isControlledBy(game.getControllerId(damagedEvent.getTargetId())))
.mapToInt(GameEvent::getAmount)
.sum();
if (damage < 1) {
return false;
}
this.getEffects().setValue("damage", damage);
return true;
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.i;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
@ -14,9 +15,11 @@ import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterSpell;
import mage.filter.StaticFilters;
import mage.filter.common.FilterInstantOrSorcerySpell;
import mage.filter.predicate.other.HasOnlySingleTargetPermanentPredicate;
import mage.game.Game;
import mage.game.events.DamagedBatchForPermanentsEvent;
import mage.game.events.DamagedPermanentEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
@ -51,9 +54,9 @@ public final class ImodaneThePyrohammer extends CardImpl {
}
}
class ImodaneThePyrohammerTriggeredAbility extends TriggeredAbilityImpl {
class ImodaneThePyrohammerTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
private static final FilterSpell filter = new FilterSpell("instant or sorcery spell you control that targets only a single creature");
private static final FilterSpell filter = new FilterInstantOrSorcerySpell("instant or sorcery spell you control that targets only a single creature");
static {
filter.add(TargetController.YOU.getControllerPredicate());
@ -83,29 +86,28 @@ class ImodaneThePyrohammerTriggeredAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PERMANENTS;
}
@Override
public boolean checkEvent(DamagedPermanentEvent event, Game game) {
MageObject sourceObject = game.getObject(event.getSourceId());
Permanent target = game.getPermanentOrLKIBattlefield(event.getTargetId());
// We keep only the events
// 1/ That have sourceId matching the spell filter
// 2/ That have targetId as the spell's only target
return target != null
&& sourceObject instanceof StackObject
&& filter.match((StackObject) sourceObject, getControllerId(), this, game)
&& target.getId().equals(((StackObject) sourceObject).getStackAbility().getFirstTarget());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForPermanentsEvent dEvent = (DamagedBatchForPermanentsEvent) event;
int damage = dEvent
.getEvents()
int damage = getFilteredEvents((DamagedBatchForPermanentsEvent) event, game)
.stream()
.filter(damagedEvent -> {
MageObject sourceObject = game.getObject(damagedEvent.getSourceId());
Permanent target = game.getPermanentOrLKIBattlefield(damagedEvent.getTargetId());
// We keep only the events
// 1/ That have sourceId matching the spell filter
// 2/ That have targetId as the spell's only target
return sourceObject != null && target != null
&& sourceObject instanceof StackObject
&& filter.match((StackObject) sourceObject, controllerId, this, game)
&& target.getId().equals(((StackObject) sourceObject).getStackAbility().getFirstTarget());
})
.mapToInt(GameEvent::getAmount)
.sum();
if (damage < 1) {
return false;
}
this.getEffects().setValue(ImodaneThePyrohammerDynamicValue.IMODANE_VALUE_KEY, damage);
return true;
}

View file

@ -1,13 +1,12 @@
package mage.cards.i;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
import mage.abilities.effects.keyword.InvestigateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -20,7 +19,7 @@ public final class InnocentBystander extends CardImpl {
public InnocentBystander(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.CITIZEN);
this.power = new MageInt(2);
@ -41,10 +40,10 @@ public final class InnocentBystander extends CardImpl {
}
}
class InnocentBystanderTriggeredAbility extends TriggeredAbilityImpl {
class InnocentBystanderTriggeredAbility extends DealtDamageToSourceTriggeredAbility {
InnocentBystanderTriggeredAbility() {
super(Zone.BATTLEFIELD, new InvestigateEffect(), false);
super(new InvestigateEffect(), false);
setTriggerPhrase("Whenever {this} is dealt 3 or more damage, ");
}
@ -57,13 +56,8 @@ class InnocentBystanderTriggeredAbility extends TriggeredAbilityImpl {
return new InnocentBystanderTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getTargetId().equals(getSourceId()) && event.getAmount() >= 3;
return event.getAmount() >= 3 && super.checkTrigger(event, game);
}
}

View file

@ -1,10 +1,11 @@
package mage.cards.j;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
@ -13,13 +14,12 @@ import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePlayerEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.JaceCunningCastawayIllusionToken;
import mage.target.targetpointer.FixedTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
@ -36,7 +36,7 @@ public final class JaceCunningCastaway extends CardImpl {
this.setStartingLoyalty(3);
// +1: Whenever one or more creatures you control deal combat damage to a player this turn, draw a card, then discard a card.
this.addAbility(new LoyaltyAbility(new JaceCunningCastawayEffect1(), 1));
this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(new JaceCunningCastawayDamageTriggeredAbility()), 1));
// -2: Create a 2/2 blue Illusion creature token with "When this creature becomes the target of a spell, sacrifice it."
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new JaceCunningCastawayIllusionToken()), -2));
@ -55,36 +55,11 @@ public final class JaceCunningCastaway extends CardImpl {
}
}
class JaceCunningCastawayEffect1 extends OneShotEffect {
JaceCunningCastawayEffect1() {
super(Outcome.DrawCard);
this.staticText = "Whenever one or more creatures you control deal combat damage to a player this turn, draw a card, then discard a card";
}
private JaceCunningCastawayEffect1(final JaceCunningCastawayEffect1 effect) {
super(effect);
}
@Override
public JaceCunningCastawayEffect1 copy() {
return new JaceCunningCastawayEffect1(this);
}
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new JaceCunningCastawayDamageTriggeredAbility();
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}
class JaceCunningCastawayDamageTriggeredAbility extends DelayedTriggeredAbility {
private final List<UUID> damagedPlayerIds = new ArrayList<>();
class JaceCunningCastawayDamageTriggeredAbility extends DelayedTriggeredAbility implements BatchTriggeredAbility<DamagedPlayerEvent> {
JaceCunningCastawayDamageTriggeredAbility() {
super(new DrawDiscardControllerEffect(1, 1), Duration.EndOfTurn, false);
setTriggerPhrase("Whenever one or more creatures you control deal combat damage to a player this turn, ");
}
private JaceCunningCastawayDamageTriggeredAbility(final JaceCunningCastawayDamageTriggeredAbility ability) {
@ -102,23 +77,19 @@ class JaceCunningCastawayDamageTriggeredAbility extends DelayedTriggeredAbility
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForOnePlayerEvent dEvent = (DamagedBatchForOnePlayerEvent) event;
int damageFromYours = dEvent.getEvents()
.stream()
.filter(ev -> ev.getSourceId().equals(controllerId))
.mapToInt(GameEvent::getAmount)
.sum();
return dEvent.isCombatDamage() && damageFromYours > 0;
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!event.isCombatDamage()) {
return false;
}
Permanent permanent = game.getPermanent(event.getSourceId());
return permanent != null && permanent.isCreature(game) && permanent.isControlledBy(getControllerId());
}
@Override
public String getRule() {
return "Whenever one or more creatures you control deal combat damage to a player this turn, draw a card, then discard a card";
public boolean checkTrigger(GameEvent event, Game game) {
return !getFilteredEvents((DamagedBatchForOnePlayerEvent) event, game).isEmpty();
}
}
class JaceCunningCastawayCopyEffect extends OneShotEffect {

View file

@ -2,18 +2,19 @@ package mage.cards.j;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
@ -35,7 +36,7 @@ public final class Justice extends CardImpl {
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl<>("{W}{W}"))));
// Whenever a red creature or spell deals damage, Justice deals that much damage to that creature's or spell's controller.
this.addAbility(new JusticeTriggeredAbility(new JusticeEffect()));
this.addAbility(new JusticeTriggeredAbility());
}
private Justice(final Justice card) {
@ -48,10 +49,10 @@ public final class Justice extends CardImpl {
}
}
class JusticeTriggeredAbility extends TriggeredAbilityImpl {
class JusticeTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedEvent> {
public JusticeTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
JusticeTriggeredAbility() {
super(Zone.BATTLEFIELD, new JusticeEffect());
}
private JusticeTriggeredAbility(final JusticeTriggeredAbility ability) {
@ -65,8 +66,7 @@ class JusticeTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_BY_SOURCE;
}
@Override

View file

@ -2,7 +2,7 @@ package mage.cards.k;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -39,7 +39,7 @@ public final class KaitoDancingShadow extends CardImpl {
this.setStartingLoyalty(3);
// Whenever one or more creatures you control deal combat damage to a player, you may return one of them to its owner's hand. If you do, you may activate loyalty abilities of Kaito twice this turn rather than only once.
Ability ability = new DealCombatDamageControlledTriggeredAbility(new KaitoDancingShadowEffect(), SetTargetPointer.PLAYER);
Ability ability = new OneOrMoreCombatDamagePlayerTriggeredAbility(new KaitoDancingShadowEffect(), SetTargetPointer.PLAYER);
ability.addWatcher(new DamagedPlayerThisCombatWatcher());
this.addAbility(ability);

View file

@ -2,6 +2,7 @@ package mage.cards.k;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldOneOrMoreTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@ -19,12 +20,10 @@ import mage.game.events.ZoneChangeBatchEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
@ -69,7 +68,7 @@ public final class KambalProfiteeringMayor extends CardImpl {
}
}
class KambalProfiteeringMayorTriggeredAbility extends TriggeredAbilityImpl {
class KambalProfiteeringMayorTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
KambalProfiteeringMayorTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
@ -91,19 +90,22 @@ class KambalProfiteeringMayorTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeBatchEvent zEvent = (ZoneChangeBatchEvent) event;
Player controller = game.getPlayer(this.controllerId);
if (controller == null) {
public boolean checkEvent(ZoneChangeEvent event, Game game) {
if (event.getToZone() != Zone.BATTLEFIELD) {
return false;
}
List<UUID> tokensIds = zEvent.getEvents()
if (!game.getOpponents(getControllerId()).contains(event.getPlayerId())) {
return false;
}
Permanent permanent = event.getTarget();
return permanent instanceof PermanentToken;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
List<UUID> tokensIds = getFilteredEvents((ZoneChangeBatchEvent) event, game)
.stream()
.filter(zce -> zce.getToZone() == Zone.BATTLEFIELD // keep enter the battlefield
&& controller.hasOpponent(zce.getPlayerId(), game)) // & under your opponent's control
.map(ZoneChangeEvent::getTarget)
.filter(Objects::nonNull)
.filter(PermanentToken.class::isInstance) // collect only tokens
.map(Permanent::getId)
.collect(Collectors.toList());
if (tokensIds.isEmpty()) {

View file

@ -4,7 +4,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
@ -47,7 +47,7 @@ public final class KastralTheWindcrested extends CardImpl {
// Whenever one or more Birds you control deal combat damage to a player, choose one --
// * You may put a Bird creature card from your hand or graveyard onto the battlefield with a finality counter on it.
Ability ability = new DealCombatDamageControlledTriggeredAbility(Zone.BATTLEFIELD,
Ability ability = new OneOrMoreCombatDamagePlayerTriggeredAbility(Zone.BATTLEFIELD,
new KastralTheWindcrestedEffect(), filter, SetTargetPointer.NONE, false);
// * Put a +1/+1 counter on each Bird you control.
@ -116,4 +116,4 @@ class KastralTheWindcrestedEffect extends OneShotEffect {
}
return true;
}
}
}

View file

@ -2,6 +2,7 @@ package mage.cards.k;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
@ -34,11 +35,7 @@ import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
import mage.util.functions.CopyApplier;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author DominionSpy
@ -84,7 +81,7 @@ public final class KayaSpiritsJustice extends CardImpl {
}
}
class KayaSpiritsJusticeTriggeredAbility extends TriggeredAbilityImpl {
class KayaSpiritsJusticeTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
KayaSpiritsJusticeTriggeredAbility() {
super(Zone.BATTLEFIELD, new KayaSpiritsJusticeCopyEffect(), false);
@ -107,44 +104,34 @@ class KayaSpiritsJusticeTriggeredAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
}
@Override
public boolean checkEvent(ZoneChangeEvent event, Game game) {
if (event.getToZone() != Zone.EXILED) {
return false;
}
switch (event.getFromZone()) {
case BATTLEFIELD:
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
return permanent != null && StaticFilters.FILTER_CONTROLLED_CREATURE.match(permanent, getControllerId(), this, game);
case GRAVEYARD:
Card card = game.getCard(event.getTargetId());
return card != null && card.isOwnedBy(getControllerId()) && StaticFilters.FILTER_CARD_CREATURE.match(card, getControllerId(), this, game);
default:
return false;
}
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeBatchEvent zEvent = (ZoneChangeBatchEvent) event;
Set<Card> battlefieldCards = zEvent.getEvents()
Cards cards = new CardsImpl();
getFilteredEvents((ZoneChangeBatchEvent) event, game)
.stream()
.filter(e -> e.getFromZone() == Zone.BATTLEFIELD)
.filter(e -> e.getToZone() == Zone.EXILED)
.map(ZoneChangeEvent::getTargetId)
.filter(Objects::nonNull)
.map(game::getCard)
.filter(Objects::nonNull)
.filter(card -> {
Permanent permanent = game.getPermanentOrLKIBattlefield(card.getId());
return StaticFilters.FILTER_PERMANENT_CREATURE
.match(permanent, getControllerId(), this, game);
})
.collect(Collectors.toSet());
Set<Card> graveyardCards = zEvent.getEvents()
.stream()
.filter(e -> e.getFromZone() == Zone.GRAVEYARD)
.filter(e -> e.getToZone() == Zone.EXILED)
.map(ZoneChangeEvent::getTargetId)
.filter(Objects::nonNull)
.map(game::getCard)
.filter(Objects::nonNull)
.filter(card -> StaticFilters.FILTER_CARD_CREATURE
.match(card, getControllerId(), this, game))
.collect(Collectors.toSet());
Set<Card> cards = new HashSet<>(battlefieldCards);
cards.addAll(graveyardCards);
.map(GameEvent::getTargetId)
.forEach(cards::add);
if (cards.isEmpty()) {
return false;
}
getEffects().setTargetPointer(new FixedTargets(new CardsImpl(cards), game));
getEffects().setTargetPointer(new FixedTargets(cards, game));
return true;
}
}

View file

@ -1,29 +1,26 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealtDamageAnyTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class KazarovSengirPureblood extends CardImpl {
@ -40,7 +37,8 @@ public final class KazarovSengirPureblood extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever a creature an opponent controls is dealt damage, put a +1/+1 counter on Kazarov, Sengir Pureblood.
this.addAbility(new KazarovSengirPurebloodTriggeredAbility());
this.addAbility(new DealtDamageAnyTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()),
StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE, SetTargetPointer.NONE, false));
// {3}{R}: Kazarov deals 2 damage to target creature.
Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{3}{R}"));
@ -57,37 +55,3 @@ public final class KazarovSengirPureblood extends CardImpl {
return new KazarovSengirPureblood(this);
}
}
class KazarovSengirPurebloodTriggeredAbility extends TriggeredAbilityImpl {
public KazarovSengirPurebloodTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
}
private KazarovSengirPurebloodTriggeredAbility(final KazarovSengirPurebloodTriggeredAbility effect) {
super(effect);
}
@Override
public KazarovSengirPurebloodTriggeredAbility copy() {
return new KazarovSengirPurebloodTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
return permanent!=null
&& permanent.isCreature(game)
&& game.getOpponents(permanent.getControllerId()).contains(this.getControllerId());
}
@Override
public String getRule() {
return "Whenever a creature an opponent controls is dealt damage, put a +1/+1 counter on {this}.";
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.k;
import mage.MageInt;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -30,7 +30,7 @@ public final class KeeperOfFables extends CardImpl {
this.toughness = new MageInt(5);
// Whenever one or more non-Human creatures you control deal combat damage to a player, draw a card.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new DrawCardSourceControllerEffect(1), filter));
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), filter));
}
private KeeperOfFables(final KeeperOfFables card) {
@ -41,4 +41,4 @@ public final class KeeperOfFables extends CardImpl {
public KeeperOfFables copy() {
return new KeeperOfFables(this);
}
}
}

View file

@ -1,63 +1,48 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.CardsInHandCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.ComparisonType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.constants.*;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class KiyomaroFirstToStand extends CardImpl {
public KiyomaroFirstToStand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Kiyomaro, First to Stand's power and toughness are each equal to the number of cards in your hand.
DynamicValue xValue= CardsInControllerHandCount.instance;
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(xValue)));
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(CardsInControllerHandCount.instance)));
// As long as you have four or more cards in hand, Kiyomaro has vigilance.
Condition condition = new CardsInHandCondition(ComparisonType.MORE_THAN,3);
Condition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 3);
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield), condition,
"As long as you have four or more cards in hand, {this} has vigilance"));
this.addAbility(ability);
// Whenever Kiyomaro deals damage, if you have seven or more cards in hand, you gain 7 life.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new KiyomaroFirstToStandDealsDamageTriggeredAbility(),
new CardsInHandCondition(ComparisonType.MORE_THAN, 6),
"Whenever {this} deals damage, if you have seven or more cards in hand, you gain 7 life"
));
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(7))
.withInterveningIf(new CardsInHandCondition(ComparisonType.OR_GREATER, 7)));
}
private KiyomaroFirstToStand(final KiyomaroFirstToStand card) {
@ -69,37 +54,3 @@ public final class KiyomaroFirstToStand extends CardImpl {
return new KiyomaroFirstToStand(this);
}
}
class KiyomaroFirstToStandDealsDamageTriggeredAbility extends TriggeredAbilityImpl {
public KiyomaroFirstToStandDealsDamageTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(7), false);
}
private KiyomaroFirstToStandDealsDamageTriggeredAbility(final KiyomaroFirstToStandDealsDamageTriggeredAbility ability) {
super(ability);
}
@Override
public KiyomaroFirstToStandDealsDamageTriggeredAbility copy() {
return new KiyomaroFirstToStandDealsDamageTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER
|| event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) {
for (Effect effect : this.getEffects()) {
effect.setValue("damage", event.getAmount());
}
return true;
}
return false;
}
}

View file

@ -1,9 +1,9 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@ -11,26 +11,27 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class KjeldoranGargoyle extends CardImpl {
public KjeldoranGargoyle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}");
this.subtype.add(SubType.GARGOYLE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// Whenever Kjeldoran Gargoyle deals damage, you gain that much life.
this.addAbility(new DealsDamageGainLifeSourceTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)));
}
private KjeldoranGargoyle(final KjeldoranGargoyle card) {
@ -41,4 +42,4 @@ public final class KjeldoranGargoyle extends CardImpl {
public KjeldoranGargoyle copy() {
return new KjeldoranGargoyle(this);
}
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.k;
import mage.MageInt;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ruleModifying.CantCastDuringYourTurnEffect;
@ -39,7 +39,7 @@ public final class KutzilMalametExemplar extends CardImpl {
this.addAbility(new SimpleStaticAbility(new CantCastDuringYourTurnEffect()));
// Whenever one or more creatures you control each with power greater than its base power deals combat damage to a player, draw a card.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)
.setTriggerPhrase("Whenever one or more creatures you control each with power greater than its base power"
+ " deals combat damage to a player, ")
);

View file

@ -1,6 +1,7 @@
package mage.cards.l;
import mage.MageInt;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
@ -16,7 +17,6 @@ import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeBatchEvent;
import mage.game.events.ZoneChangeEvent;
import java.util.Objects;
import java.util.UUID;
/**
@ -58,7 +58,7 @@ public final class LaeliaTheBladeReforged extends CardImpl {
}
}
class LaeliaTheBladeReforgedAddCountersTriggeredAbility extends TriggeredAbilityImpl {
class LaeliaTheBladeReforgedAddCountersTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<ZoneChangeEvent> {
LaeliaTheBladeReforgedAddCountersTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false);
@ -78,18 +78,21 @@ class LaeliaTheBladeReforgedAddCountersTriggeredAbility extends TriggeredAbility
return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH;
}
@Override
public boolean checkEvent(ZoneChangeEvent event, Game game) {
if (event.getToZone() != Zone.EXILED) {
return false;
}
if (event.getFromZone() != Zone.LIBRARY && event.getFromZone() != Zone.GRAVEYARD) {
return false;
}
Card card = game.getCard(event.getTargetId());
return card != null && card.isOwnedBy(getControllerId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeBatchEvent zEvent = (ZoneChangeBatchEvent) event;
return zEvent.getEvents()
.stream()
.filter(e -> e.getFromZone() == Zone.LIBRARY || e.getFromZone() == Zone.GRAVEYARD)
.filter(e -> e.getToZone() == Zone.EXILED)
.map(ZoneChangeEvent::getTargetId)
.map(game::getCard)
.filter(Objects::nonNull)
.map(Card::getOwnerId)
.anyMatch(this::isControlledBy);
return !getFilteredEvents((ZoneChangeBatchEvent) event, game).isEmpty();
}
@Override

View file

@ -1,14 +1,12 @@
package mage.cards.l;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.YoureDealtDamageTriggeredAbility;
import mage.abilities.dynamicvalue.common.ControllerLifeCount;
import mage.abilities.effects.Effect;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.LoseGameSourceControllerEffect;
@ -19,38 +17,36 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetSacrifice;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class Lich extends CardImpl {
public Lich(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{B}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}{B}{B}");
// As Lich enters the battlefield, you lose life equal to your life total.
this.addAbility(new EntersBattlefieldAbility(new LoseLifeSourceControllerEffect(ControllerLifeCount.instance), null, "As Lich enters the battlefield, you lose life equal to your life total.", null));
// You don't lose the game for having 0 or less life.
this.addAbility(new SimpleStaticAbility(new DontLoseByZeroOrLessLifeEffect(Duration.WhileOnBattlefield)));
// If you would gain life, draw that many cards instead.
this.addAbility(new SimpleStaticAbility(new LichLifeGainReplacementEffect()));
// Whenever you're dealt damage, sacrifice that many nontoken permanents. If you can't, you lose the game.
this.addAbility(new LichDamageTriggeredAbility());
this.addAbility(new YoureDealtDamageTriggeredAbility(new LichDamageEffect(), false));
// When Lich is put into a graveyard from the battlefield, you lose the game.
this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new LoseGameSourceControllerEffect()));
}
@ -101,92 +97,46 @@ class LichLifeGainReplacementEffect extends ReplacementEffectImpl {
}
}
class LichDamageTriggeredAbility extends TriggeredAbilityImpl {
LichDamageTriggeredAbility() {
super(Zone.BATTLEFIELD, new LichDamageEffect(), false);
}
private LichDamageTriggeredAbility(final LichDamageTriggeredAbility ability) {
super(ability);
}
@Override
public LichDamageTriggeredAbility copy() {
return new LichDamageTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getControllerId())) {
for (Effect effect : this.getEffects()) {
if (effect instanceof LichDamageEffect) {
((LichDamageEffect) effect).setAmount(event.getAmount());
}
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you're dealt damage, sacrifice that many nontoken permanents. If you can't, you lose the game.";
}
}
class LichDamageEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("nontoken permanent");
static {
filter.add(TokenPredicate.FALSE);
}
private int amount = 0;
LichDamageEffect() {
super(Outcome.Sacrifice);
this.staticText = "sacrifice that many nontoken permanents. If you can't, you lose the game";
}
private LichDamageEffect(final LichDamageEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
public LichDamageEffect copy() {
return new LichDamageEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
TargetSacrifice target = new TargetSacrifice(amount, filter);
if (target.canChoose(controller.getId(), source, game)) {
if (controller.choose(Outcome.Sacrifice, target, source, game)) {
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
permanent.sacrifice(source, game);
}
}
return true;
if (controller == null) {
return false;
}
TargetSacrifice target = new TargetSacrifice(SavedDamageValue.MANY.calculate(game, source, this), filter);
if (target.canChoose(controller.getId(), source, game) && controller.choose(Outcome.Sacrifice, target, source, game)) {
for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
permanent.sacrifice(source, game);
}
}
controller.lost(game);
return true;
}
return false;
}
public void setAmount(int amount) {
this.amount = amount;
controller.lost(game);
return true;
}
}

View file

@ -1,12 +1,12 @@
package mage.cards.l;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.GainLifeControllerTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.SavedGainedLifeValue;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@ -56,7 +56,7 @@ public final class LichsMastery extends CardImpl {
));
// Whenever you lose life, for each 1 life you lost, exile a permanent you control or a card from your hand or graveyard.
this.addAbility(new LichsMasteryLoseLifeTriggeredAbility());
this.addAbility(new LoseLifeTriggeredAbility(new LichsMasteryLoseLifeEffect()));
// When Lich's Mastery leaves the battlefield, you lose the game.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false));
@ -99,57 +99,15 @@ class LichsMasteryCantLoseEffect extends ContinuousRuleModifyingEffectImpl {
}
}
class LichsMasteryLoseLifeTriggeredAbility extends TriggeredAbilityImpl {
public LichsMasteryLoseLifeTriggeredAbility() {
super(Zone.BATTLEFIELD, new LichsMasteryLoseLifeEffect(), false);
}
private LichsMasteryLoseLifeTriggeredAbility(final LichsMasteryLoseLifeTriggeredAbility ability) {
super(ability);
}
@Override
public LichsMasteryLoseLifeTriggeredAbility copy() {
return new LichsMasteryLoseLifeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(this.getControllerId())) {
for (Effect effect : this.getEffects()) {
if (effect instanceof LichsMasteryLoseLifeEffect) {
((LichsMasteryLoseLifeEffect) effect).setAmount(event.getAmount());
}
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you lose life, for each 1 life you lost, exile a permanent you control or a card from your hand or graveyard.";
}
}
class LichsMasteryLoseLifeEffect extends OneShotEffect {
private int amount = 0;
public LichsMasteryLoseLifeEffect() {
LichsMasteryLoseLifeEffect() {
super(Outcome.Exile);
this.staticText = "for each 1 life you lost, exile a permanent you control or a card from your hand or graveyard.";
this.staticText = "for each 1 life you lost, exile a permanent you control or a card from your hand or graveyard";
}
private LichsMasteryLoseLifeEffect(final LichsMasteryLoseLifeEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
@ -165,7 +123,7 @@ class LichsMasteryLoseLifeEffect extends OneShotEffect {
}
FilterPermanent filter = new FilterPermanent();
filter.add(new ControllerIdPredicate(controller.getId()));
for (int i = 0; i < amount; i++) {
for (int i = 0; i < SavedLifeLossValue.MANY.calculate(game, source, this); i++) {
int handCount = controller.getHand().size();
int graveCount = controller.getGraveyard().size();
int permCount = game.getBattlefield().getActivePermanents(filter, controller.getId(), game).size();
@ -182,7 +140,7 @@ class LichsMasteryLoseLifeEffect extends OneShotEffect {
if (card != null) {
controller.moveCards(card, Zone.EXILED, source, game);
}
} else if (graveCount > 0) {
} else {
Target target = new TargetCardInYourGraveyard(1, 1, new FilterCard(), true);
target.choose(Outcome.Exile, source.getControllerId(), source.getSourceId(), source, game);
Card card = controller.getGraveyard().get(target.getFirstTarget(), game);
@ -194,7 +152,4 @@ class LichsMasteryLoseLifeEffect extends OneShotEffect {
return true;
}
public void setAmount(int amount) {
this.amount = amount;
}
}

View file

@ -1,37 +1,33 @@
package mage.cards.l;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.common.SacrificeControllerEffect;
import mage.abilities.effects.common.SacrificeEffect;
import mage.abilities.effects.common.continuous.DontLoseByZeroOrLessLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class LichsTomb extends CardImpl {
public LichsTomb(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// You don't lose the game for having 0 or less life.
this.addAbility(new SimpleStaticAbility(new DontLoseByZeroOrLessLifeEffect(Duration.WhileOnBattlefield)));
// Whenever you lose life, sacrifice a permanent for each 1 life you lost.
this.addAbility(new LichsTombTriggeredAbility());
this.addAbility(new LoseLifeTriggeredAbility(new SacrificeControllerEffect(
StaticFilters.FILTER_PERMANENT, SavedLifeLossValue.MANY, ""
).setText("sacrifice a permanent for each 1 life you lost")));
}
private LichsTomb(final LichsTomb card) {
@ -43,38 +39,3 @@ public final class LichsTomb extends CardImpl {
return new LichsTomb(this);
}
}
class LichsTombTriggeredAbility extends TriggeredAbilityImpl {
LichsTombTriggeredAbility() {
super(Zone.BATTLEFIELD, new SacrificeControllerEffect(new FilterPermanent(), 0, ""), false);
}
private LichsTombTriggeredAbility(final LichsTombTriggeredAbility ability) {
super(ability);
}
@Override
public LichsTombTriggeredAbility copy() {
return new LichsTombTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(this.getControllerId())) {
((SacrificeEffect) this.getEffects().get(0)).setAmount(StaticValue.get(event.getAmount()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you lose life, sacrifice a permanent for each 1 life you lost.";
}
}

View file

@ -1,39 +1,33 @@
package mage.cards.l;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.common.YoureDealtDamageTriggeredAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.TargetPermanent;
import mage.target.common.TargetArtifactPermanent;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class LivingArtifact extends CardImpl {
public LivingArtifact(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}");
this.subtype.add(SubType.AURA);
// Enchant artifact
@ -42,13 +36,14 @@ public final class LivingArtifact extends CardImpl {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit));
Ability ability = new EnchantAbility(auraTarget);
this.addAbility(ability);
// Whenever you're dealt damage, put that many vitality counters on Living Artifact.
this.addAbility(new LivingArtifactTriggeredAbility());
this.addAbility(new YoureDealtDamageTriggeredAbility(new AddCountersSourceEffect(
CounterType.VITALITY.createInstance(), SavedDamageValue.MANY), false));
// At the beginning of your upkeep, you may remove a vitality counter from Living Artifact. If you do, you gain 1 life.
//TODO make this a custom ability- it's really not intervening if because you should be able to add counters in response to this trigger
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new GainLifeEffect(1),
new RemoveCountersSourceCost(CounterType.VITALITY.createInstance(1)))),
new SourceHasCounterCondition(CounterType.VITALITY, 1), "At the beginning of your upkeep, you may remove a vitality counter from {this}. If you do, you gain 1 life"));
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid(new GainLifeEffect(1),
new RemoveCountersSourceCost(CounterType.VITALITY.createInstance(1)))));
}
private LivingArtifact(final LivingArtifact card) {
@ -60,59 +55,3 @@ public final class LivingArtifact extends CardImpl {
return new LivingArtifact(this);
}
}
class LivingArtifactTriggeredAbility extends TriggeredAbilityImpl {
public LivingArtifactTriggeredAbility() {
super(Zone.BATTLEFIELD, new LivingArtifactEffect(), false);
}
private LivingArtifactTriggeredAbility(final LivingArtifactTriggeredAbility ability) {
super(ability);
}
@Override
public LivingArtifactTriggeredAbility copy() {
return new LivingArtifactTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getControllerId())) {
this.getEffects().get(0).setValue("damageAmount", event.getAmount());
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you're dealt damage, put that many vitality counters on {this}.";
}
}
class LivingArtifactEffect extends OneShotEffect {
LivingArtifactEffect() {
super(Outcome.Benefit);
}
private LivingArtifactEffect(final LivingArtifactEffect effect) {
super(effect);
}
@Override
public LivingArtifactEffect copy() {
return new LivingArtifactEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return new AddCountersSourceEffect(CounterType.VITALITY.createInstance((Integer) this.getValue("damageAmount"))).apply(game, source);
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.l;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -21,7 +22,7 @@ import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.DamagedBatchAllEvent;
import mage.game.events.DamagedBatchBySourceEvent;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -96,7 +97,7 @@ class LongRiverLurkerEffect extends OneShotEffect {
}
}
class LongRiverLurkerTriggeredAbility extends DelayedTriggeredAbility {
class LongRiverLurkerTriggeredAbility extends DelayedTriggeredAbility implements BatchTriggeredAbility<DamagedEvent> {
private final MageObjectReference mor;
@ -118,16 +119,13 @@ class LongRiverLurkerTriggeredAbility extends DelayedTriggeredAbility {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ALL;
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_BY_SOURCE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return ((DamagedBatchAllEvent) event)
.getEvents()
.stream()
.filter(DamagedEvent::isCombatDamage)
.anyMatch(e -> mor.refersTo(e.getAttackerId(), game));
return ((DamagedBatchBySourceEvent) event).isCombatDamage()
&& mor.refersTo(event.getSourceId(), game);
}
@Override

View file

@ -2,6 +2,7 @@ package mage.cards.m;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@ -13,9 +14,7 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedBatchForPermanentsEvent;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.events.*;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TreasureToken;
import mage.target.common.TargetOpponentsCreaturePermanent;
@ -57,7 +56,7 @@ public final class MagmaticGalleon extends CardImpl {
}
}
class MagmaticGalleonTriggeredAbility extends TriggeredAbilityImpl {
class MagmaticGalleonTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPermanentEvent> {
MagmaticGalleonTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new TreasureToken()));
@ -78,19 +77,19 @@ class MagmaticGalleonTriggeredAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PERMANENTS;
}
@Override
public boolean checkEvent(DamagedPermanentEvent event, Game game) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
return permanent != null
&& permanent.isCreature(game)
&& game.getOpponents(getControllerId()).contains(permanent.getControllerId())
&& !event.isCombatDamage();
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
int damage = ((DamagedBatchForPermanentsEvent) event)
.getEvents()
int damage = getFilteredEvents((DamagedBatchForPermanentsEvent) event, game)
.stream()
.filter(damagedEvent -> {
if (damagedEvent.isCombatDamage()) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(damagedEvent.getTargetId());
return permanent != null && permanent.isCreature(game)
&& game.getOpponents(this.getControllerId()).contains(permanent.getControllerId());
})
.mapToInt(DamagedEvent::getExcess)
.sum();
return damage >= 1;

View file

@ -1,6 +1,7 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlyingAbility;
@ -12,8 +13,8 @@ import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.DamagedBatchForPlayersEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TreasureToken;
@ -56,7 +57,7 @@ public final class MalcolmKeenEyedNavigator extends CardImpl {
}
}
class MalcolmKeenEyedNavigatorTriggeredAbility extends TriggeredAbilityImpl {
class MalcolmKeenEyedNavigatorTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
MalcolmKeenEyedNavigatorTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
@ -72,20 +73,24 @@ class MalcolmKeenEyedNavigatorTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedBatchForPlayersEvent dEvent = (DamagedBatchForPlayersEvent) event;
Set<UUID> opponents = new HashSet<>();
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
if (permanent == null
|| !permanent.isControlledBy(getControllerId())
|| !permanent.hasSubtype(SubType.PIRATE, game)
|| !game.getOpponents(getControllerId()).contains(damagedEvent.getTargetId())) {
continue;
}
opponents.add(damagedEvent.getTargetId());
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!game.getOpponents(getControllerId()).contains(event.getTargetId())) {
return false;
}
if (opponents.size() < 1) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return permanent != null
&& permanent.isControlledBy(getControllerId())
&& permanent.hasSubtype(SubType.PIRATE, game);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Set<UUID> opponents = new HashSet<>();
getFilteredEvents((DamagedBatchForPlayersEvent) event, game)
.stream()
.map(GameEvent::getTargetId)
.forEach(opponents::add);
if (opponents.isEmpty()) {
return false;
}
this.getEffects().clear();

View file

@ -1,16 +1,16 @@
package mage.cards.m;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.GainLifeControllerTriggeredAbility;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CastFromEverywhereSourceCondition;
import mage.abilities.condition.common.HellbentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.dynamicvalue.common.SavedGainedLifeValue;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseGameSourceControllerEffect;
import mage.abilities.effects.common.continuous.DontLoseByZeroOrLessLifeEffect;
@ -21,9 +21,6 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
@ -58,7 +55,12 @@ public final class MarinaVendrellsGrimoire extends CardImpl {
));
// Whenever you lose life, discard that many cards. Then if you have no cards in hand, you lose the game.
this.addAbility(new MarinaVendrellsGrimoireTriggeredAbility());
Ability ability2 = new LoseLifeTriggeredAbility(new DiscardControllerEffect(SavedLifeLossValue.MANY));
ability2.addEffect(new ConditionalOneShotEffect(
new LoseGameSourceControllerEffect(), HellbentCondition.instance,
"Then if you have no cards in hand, you lose the game"
));
this.addAbility(ability2);
}
private MarinaVendrellsGrimoire(final MarinaVendrellsGrimoire card) {
@ -70,38 +72,3 @@ public final class MarinaVendrellsGrimoire extends CardImpl {
return new MarinaVendrellsGrimoire(this);
}
}
class MarinaVendrellsGrimoireTriggeredAbility extends TriggeredAbilityImpl {
MarinaVendrellsGrimoireTriggeredAbility() {
super(Zone.BATTLEFIELD, new DiscardControllerEffect(SavedDamageValue.MANY));
this.addEffect(new ConditionalOneShotEffect(
new LoseGameSourceControllerEffect(), HellbentCondition.instance,
"Then if you have no cards in hand, you lose the game"
));
this.setTriggerPhrase("Whenever you lose life, ");
}
private MarinaVendrellsGrimoireTriggeredAbility(final MarinaVendrellsGrimoireTriggeredAbility ability) {
super(ability);
}
@Override
public MarinaVendrellsGrimoireTriggeredAbility copy() {
return new MarinaVendrellsGrimoireTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) {
return false;
}
this.getEffects().setValue("damage", event.getAmount());
return true;
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAllEffect;
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
@ -45,7 +45,7 @@ public final class MidnightPathlighter extends CardImpl {
)));
// Whenever one or more creatures you control deal combat damage to a player, venture into the dungeon.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new VentureIntoTheDungeonEffect())
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(new VentureIntoTheDungeonEffect())
.addHint(CurrentDungeonHint.instance));
}

View file

@ -1,6 +1,7 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
@ -10,10 +11,10 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedBatchForOnePlayerEvent;
import mage.game.events.DamagedBatchForPlayersEvent;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
@ -45,11 +46,12 @@ public final class MindbladeRender extends CardImpl {
}
}
class MindbladeRenderTriggeredAbility extends TriggeredAbilityImpl {
class MindbladeRenderTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<DamagedPlayerEvent> {
public MindbladeRenderTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
this.addEffect(new LoseLifeSourceControllerEffect(1));
MindbladeRenderTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1, true));
this.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and"));
setTriggerPhrase("Whenever your opponents are dealt combat damage, if any of that damage was dealt by a Warrior, ");
}
private MindbladeRenderTriggeredAbility(final MindbladeRenderTriggeredAbility effect) {
@ -63,38 +65,21 @@ class MindbladeRenderTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PLAYERS;
}
@Override
public boolean checkEvent(DamagedPlayerEvent event, Game game) {
if (!event.isCombatDamage() || !game.getOpponents(getControllerId()).contains(event.getTargetId())) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
return permanent != null && permanent.isControlledBy(getControllerId()) && permanent.hasSubtype(SubType.WARRIOR, game);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player controller = game.getPlayer(getControllerId());
if (controller == null) {
return false;
}
DamagedBatchForOnePlayerEvent dEvent = (DamagedBatchForOnePlayerEvent) event;
if (!controller.hasOpponent(dEvent.getTargetId(), game)){
return false;
}
if (!dEvent.isCombatDamage()) {
return false;
}
int warriorDamage = dEvent.getEvents()
.stream()
.filter(ev -> {
Permanent attacker = game.getPermanentOrLKIBattlefield(ev.getSourceId());
return attacker != null && attacker.hasSubtype(SubType.WARRIOR, game);
})
.mapToInt(GameEvent::getAmount)
.sum();
return warriorDamage > 0;
return !getFilteredEvents((DamagedBatchForPlayersEvent) event, game).isEmpty();
}
@Override
public String getRule() {
return "Whenever your opponents are dealt combat damage, if any of that damage was dealt by a Warrior, you draw a card and you lose 1 life.";
}
}

View file

@ -1,21 +1,13 @@
package mage.cards.m;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.common.MillCardsTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.constants.TargetController;
import java.util.Set;
import java.util.UUID;
/**
@ -26,9 +18,11 @@ public final class Mindcrank extends CardImpl {
public Mindcrank(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Whenever an opponent loses life, that player puts that many cards from the top of their library into their graveyard.
// (Damage dealt by sources without infect causes loss of life.)
this.addAbility(new MindcrankTriggeredAbility());
// Whenever an opponent loses life, that player mills that many cards.
this.addAbility(new LoseLifeTriggeredAbility(
new MillCardsTargetEffect(SavedLifeLossValue.MANY),
TargetController.OPPONENT, false, true
));
}
private Mindcrank(final Mindcrank card) {
@ -40,71 +34,3 @@ public final class Mindcrank extends CardImpl {
return new Mindcrank(this);
}
}
class MindcrankTriggeredAbility extends TriggeredAbilityImpl {
public MindcrankTriggeredAbility() {
super(Zone.BATTLEFIELD, new MindcrankEffect(), false);
}
private MindcrankTriggeredAbility(final MindcrankTriggeredAbility ability) {
super(ability);
}
@Override
public MindcrankTriggeredAbility copy() {
return new MindcrankTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Set<UUID> opponents = game.getOpponents(this.getControllerId());
if (opponents.contains(event.getPlayerId())) {
for (Effect effect : this.getEffects()) {
effect.setValue("lostLife", event.getAmount());
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
}
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever an opponent loses life, that player mills that many cards.";
}
}
class MindcrankEffect extends OneShotEffect {
MindcrankEffect() {
super(Outcome.Detriment);
}
private MindcrankEffect(final MindcrankEffect effect) {
super(effect);
}
@Override
public MindcrankEffect copy() {
return new MindcrankEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
if (targetPlayer != null) {
Integer amount = (Integer) getValue("lostLife");
if (amount == null) {
amount = 0;
}
targetPlayer.millCards(amount, source, game);
}
return true;
}
}

View file

@ -33,7 +33,7 @@ public final class MireBlight extends CardImpl {
Ability ability = new EnchantAbility(auraTarget);
this.addAbility(ability);
// When enchanted creature is dealt damage, destroy it.
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DestroyAttachedToEffect("it"), false).setTriggerPhrase("When enchanted creature is dealt damage, "));
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DestroyAttachedToEffect("it")).setTriggerPhrase("When enchanted creature is dealt damage, "));
}
private MireBlight(final MireBlight card) {

View file

@ -31,7 +31,7 @@ public final class MortalWound extends CardImpl {
Ability ability = new EnchantAbility(auraTarget);
this.addAbility(ability);
// When enchanted creature is dealt damage, destroy it.
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DestroyAttachedToEffect("it"), false)
this.addAbility(new DealtDamageAttachedTriggeredAbility(new DestroyAttachedToEffect("it"))
.setTriggerPhrase("When enchanted creature is dealt damage, "));
}

View file

@ -1,23 +1,24 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author North
*/
public final class MourningThrull extends CardImpl {
public MourningThrull(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W/B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W/B}");
this.subtype.add(SubType.THRULL);
this.power = new MageInt(1);
@ -25,8 +26,9 @@ public final class MourningThrull extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever Mourning Thrull deals damage, you gain that much life.
this.addAbility(new DealsDamageGainLifeSourceTriggeredAbility());
this.addAbility(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)));
}
private MourningThrull(final MourningThrull card) {

View file

@ -3,7 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.TapAllTargetPlayerControlsEffect;
import mage.abilities.effects.common.UntapAllEffect;
@ -25,7 +25,7 @@ public final class NaturesWill extends CardImpl {
// Whenever one or more creatures you control deal combat damage to a player, tap all lands that player controls and untap all lands you control.
Effect tapAllEffect = new TapAllTargetPlayerControlsEffect(StaticFilters.FILTER_LANDS);
tapAllEffect.setText("tap all lands that player controls");
Ability ability = new DealCombatDamageControlledTriggeredAbility(tapAllEffect, SetTargetPointer.PLAYER);
Ability ability = new OneOrMoreCombatDamagePlayerTriggeredAbility(tapAllEffect, SetTargetPointer.PLAYER);
ability.addEffect(new UntapAllEffect(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS).concatBy("and"));
addAbility(ability);
}

View file

@ -1,12 +1,12 @@
package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageGainLifeSourceTriggeredAbility;
import mage.abilities.common.DealsDamageSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.common.KickedCostCondition;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.KickerAbility;
@ -14,19 +14,19 @@ import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.counters.CounterType;
/**
*
* @author LoneFox
import java.util.UUID;
/**
* @author LoneFox
*/
public final class Necravolver extends CardImpl {
public Necravolver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.VOLVER);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@ -36,14 +36,14 @@ public final class Necravolver extends CardImpl {
kickerAbility.addKickerCost("{W}");
this.addAbility(kickerAbility);
// If Necravolver was kicked with its {1}{G} kicker, it enters with two +1/+1 counters on it and with trample.
Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)),
new KickedCostCondition("{1}{G}"), "If {this} was kicked with its {1}{G} kicker, it enters with two +1/+1 counters on it and with trample.", "");
Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)),
new KickedCostCondition("{1}{G}"), "If {this} was kicked with its {1}{G} kicker, it enters with two +1/+1 counters on it and with trample.", "");
ability.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield));
this.addAbility(ability);
// If Necravolver was kicked with its {W} kicker, it enters with a +1/+1 counter on it and with "Whenever Necravolver deals damage, you gain that much life."
ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)),
new KickedCostCondition("{W}"), "If {this} was kicked with its {W} kicker, it enters with a +1/+1 counter on it and with \"Whenever {this} deals damage, you gain that much life.\"", "");
ability.addEffect(new GainAbilitySourceEffect(new DealsDamageGainLifeSourceTriggeredAbility(), Duration.WhileOnBattlefield));
ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)),
new KickedCostCondition("{W}"), "If {this} was kicked with its {W} kicker, it enters with a +1/+1 counter on it and with \"Whenever {this} deals damage, you gain that much life.\"", "");
ability.addEffect(new GainAbilitySourceEffect(new DealsDamageSourceTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH)), Duration.WhileOnBattlefield));
this.addAbility(ability);
}

View file

@ -11,7 +11,7 @@ import mage.game.permanent.token.Token;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.abilities.Ability;
import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.GoadTargetEffect;
import mage.abilities.keyword.FlyingAbility;
@ -42,7 +42,7 @@ public final class NettlingNuisance extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever one or more Faeries you control deal combat damage to a player, that player creates a 4/2 red Pirate creature token with "This creature can't block." The token is goaded for the rest of the game.
this.addAbility(new DealCombatDamageControlledTriggeredAbility(Zone.BATTLEFIELD, new NettlingNuisanceEffect(), filter, SetTargetPointer.PLAYER, false));
this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(Zone.BATTLEFIELD, new NettlingNuisanceEffect(), filter, SetTargetPointer.PLAYER, false));
}
private NettlingNuisance(final NettlingNuisance card) {

View file

@ -1,30 +1,31 @@
package mage.cards.n;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealsDamageToAnyTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class NoblePurpose extends CardImpl {
public NoblePurpose(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}");
// Whenever a creature you control deals combat damage, you gain that much life.
this.addAbility(new NoblePurposeTriggeredAbility());
this.addAbility(new DealsDamageToAnyTriggeredAbility(Zone.BATTLEFIELD,
new GainLifeEffect(SavedDamageValue.MUCH),
StaticFilters.FILTER_CONTROLLED_A_CREATURE,
SetTargetPointer.NONE, true, false
));
}
private NoblePurpose(final NoblePurpose card) {
@ -36,46 +37,3 @@ public final class NoblePurpose extends CardImpl {
return new NoblePurpose(this);
}
}
class NoblePurposeTriggeredAbility extends TriggeredAbilityImpl {
public NoblePurposeTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
}
private NoblePurposeTriggeredAbility(final NoblePurposeTriggeredAbility ability) {
super(ability);
}
@Override
public NoblePurposeTriggeredAbility copy() {
return new NoblePurposeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT
|| event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedEvent damageEvent = (DamagedEvent) event;
if (damageEvent.isCombatDamage()) {
Permanent permanent = game.getPermanent(event.getSourceId());
if (permanent != null && permanent.isCreature(game)
&& permanent.isControlledBy(this.getControllerId())) {
this.getEffects().clear();
this.getEffects().add(new GainLifeEffect(damageEvent.getAmount()));
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever a creature you control deals combat damage, you gain that much life.";
}
}

View file

@ -11,6 +11,7 @@ import mage.abilities.effects.common.counter.AddPoisonCounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
/**
*
@ -22,7 +23,9 @@ public final class NornsDecree extends CardImpl {
super(ownerId, setInfo, new CardType[] { CardType.ENCHANTMENT }, "{2}{W}");
// Whenever one or more creatures an opponent controls deal combat damage to you, that opponent gets a poison counter.
this.addAbility(new CombatDamageDealtToYouTriggeredAbility(new AddPoisonCounterTargetEffect(1).setText("that opponent gets a poison counter."), true));
this.addAbility(new CombatDamageDealtToYouTriggeredAbility(Zone.BATTLEFIELD,
new AddPoisonCounterTargetEffect(1).setText("that opponent gets a poison counter"),
true, false));
// Whenever a player attacks, if one or more players being attacked are poisoned, the attacking player draws a card.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(

View file

@ -1,31 +1,28 @@
package mage.cards.o;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.LoseLifeTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.SavedLifeLossValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoUnlessControllerPaysEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.SacrificeControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class OathOfLimDul extends CardImpl {
@ -34,7 +31,7 @@ public final class OathOfLimDul extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}");
// Whenever you lose life, for each 1 life you lost, sacrifice a permanent other than Oath of Lim-Dul unless you discard a card.
this.addAbility(new OathOfLimDulTriggeredAbility());
this.addAbility(new LoseLifeTriggeredAbility(new OathOfLimDulEffect()));
// {B}{B}: Draw a card.
this.addAbility(new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{B}{B}")));
@ -51,51 +48,17 @@ public final class OathOfLimDul extends CardImpl {
}
}
class OathOfLimDulTriggeredAbility extends TriggeredAbilityImpl {
public OathOfLimDulTriggeredAbility() {
super(Zone.BATTLEFIELD, new OathOfLimDulEffect());
}
private OathOfLimDulTriggeredAbility(final OathOfLimDulTriggeredAbility ability) {
super(ability);
}
@Override
public OathOfLimDulTriggeredAbility copy() {
return new OathOfLimDulTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(controllerId)) {
game.getState().setValue(sourceId.toString() + "oathOfLimDul", event.getAmount());
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you lose life, for each 1 life you lost, sacrifice a permanent other than {this} unless you discard a card.";
}
}
class OathOfLimDulEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("controlled permanent other than Oath of Lim-Dul to sacrifice");
private static final FilterControlledPermanent filter = new FilterControlledPermanent("controlled permanent other than {this} to sacrifice");
static {
filter.add(AnotherPredicate.instance);
}
public OathOfLimDulEffect() {
super(Outcome.Neutral);
OathOfLimDulEffect() {
super(Outcome.Detriment);
staticText = "for each 1 life you lost, sacrifice a permanent other than {this} unless you discard a card";
}
private OathOfLimDulEffect(final OathOfLimDulEffect effect) {
@ -104,34 +67,19 @@ class OathOfLimDulEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
boolean sacrificeDone = false;
int numberSacrificed = 0;
int numberToDiscard = 0;
int numberOfControlledPermanents = 0;
int amountDamage = SavedLifeLossValue.MANY.calculate(game, source, this);
Player controller = game.getPlayer(source.getControllerId());
int amountDamage = (int) game.getState().getValue(source.getSourceId().toString() + "oathOfLimDul");
if (amountDamage > 0
&& controller != null) {
TargetControlledPermanent target = new TargetControlledPermanent(0, numberOfControlledPermanents, filter, true);
target.withNotTarget(true);
if (controller.choose(Outcome.Detriment, target, source, game)) {
for (UUID targetPermanentId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetPermanentId);
if (permanent != null
&& permanent.sacrifice(source, game)) {
numberSacrificed += 1;
sacrificeDone = true;
}
}
}
numberToDiscard = amountDamage - numberSacrificed;
Cost cost = new DiscardTargetCost(new TargetCardInHand(numberToDiscard, new FilterCard("card(s) in your hand to discard")));
if (numberToDiscard > 0
&& cost.canPay(source, source, controller.getId(), game)) {
return cost.pay(source, game, source, controller.getId(), true); // discard cost paid simultaneously
}
if (amountDamage <= 0 || controller == null) {
return false;
}
return sacrificeDone;
boolean didSomething = false;
for (int i = 0; i < amountDamage; ++i) {
didSomething |= new DoUnlessControllerPaysEffect(
new SacrificeControllerEffect(StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT, 1, ""),
new DiscardCardCost()
).apply(game, source);
}
return didSomething;
}
@Override

View file

@ -1,8 +1,10 @@
package mage.cards.o;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.BatchTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
@ -58,7 +60,7 @@ public final class ObNixilisCaptiveKingpin extends CardImpl {
}
}
class ObNixilisCaptiveKingpinAbility extends TriggeredAbilityImpl {
class ObNixilisCaptiveKingpinAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility<LifeLostEvent> {
ObNixilisCaptiveKingpinAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
@ -74,28 +76,20 @@ class ObNixilisCaptiveKingpinAbility extends TriggeredAbilityImpl {
return event.getType() == GameEvent.EventType.LOST_LIFE_BATCH;
}
@Override
public boolean checkEvent(LifeLostEvent event, Game game) {
return game.getOpponents(getControllerId()).contains(event.getTargetId());
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
LifeLostBatchEvent lifeLostBatchEvent = (LifeLostBatchEvent) event;
boolean opponentLostLife = false;
boolean allis1 = true;
for (UUID targetPlayer : CardUtil.getEventTargets(lifeLostBatchEvent)) {
// skip controller
if (targetPlayer.equals(getControllerId())) {
continue;
}
opponentLostLife = true;
int lifeLost = lifeLostBatchEvent.getLifeLostByPlayer(targetPlayer);
if (lifeLost != 1) {
allis1 = false;
break;
}
List<LifeLostEvent> filteredEvents = getFilteredEvents((LifeLostBatchEvent) event, game);
if (filteredEvents.isEmpty()) {
return false;
}
return opponentLostLife && allis1;
// if here, at least one opponent lost some amount of life
return CardUtil.getEventTargets(event).stream()
.allMatch(uuid -> LifeLostBatchEvent.getLifeLostByPlayer(filteredEvents, uuid) <= 1);
}
@Override

Some files were not shown because too many files have changed in this diff Show more