fixed implementation of cards which trigger on unblocked attackers

This commit is contained in:
Evan Kranzler 2021-02-15 19:04:17 -05:00
parent 25f234cbcc
commit bb696b4210
7 changed files with 399 additions and 289 deletions

View file

@ -2,21 +2,18 @@ package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
@ -43,7 +40,6 @@ public final class CloakOfConfusion extends CardImpl {
// Whenever enchanted creature attacks and isn't blocked, you may have it assign no combat damage this turn.
// If you do, defending player discards a card at random.
this.addAbility(new CloakOfConfusionTriggeredAbility());
}
private CloakOfConfusion(final CloakOfConfusion card) {
@ -58,11 +54,12 @@ public final class CloakOfConfusion extends CardImpl {
class CloakOfConfusionTriggeredAbility extends TriggeredAbilityImpl {
public CloakOfConfusionTriggeredAbility() {
super(Zone.BATTLEFIELD, new CloakOfConfusionEffect(), true);
CloakOfConfusionTriggeredAbility() {
super(Zone.BATTLEFIELD, new DiscardTargetEffect(1, true), false);
this.addEffect(new CloakOfConfusionEffect());
}
public CloakOfConfusionTriggeredAbility(final CloakOfConfusionTriggeredAbility ability) {
private CloakOfConfusionTriggeredAbility(final CloakOfConfusionTriggeredAbility ability) {
super(ability);
}
@ -73,45 +70,34 @@ class CloakOfConfusionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARE_BLOCKERS_STEP;
return event.getType() == EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent aura = game.getPermanentOrLKIBattlefield(getSourceId());
if (aura != null) {
Permanent enchantedCreature = game.getPermanent(aura.getAttachedTo());
if (enchantedCreature != null
&& enchantedCreature.isAttacking()) {
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getBlockers().isEmpty()
&& combatGroup.getAttackers().contains(enchantedCreature.getId())) {
this.getEffects().setTargetPointer(
new FixedTarget(game.getCombat().getDefendingPlayerId(
enchantedCreature.getId(), game)));
return true;
}
}
}
Permanent aura = getSourcePermanentOrLKI(game);
if (aura != null && event.getTargetId().equals(aura.getAttachedTo())) {
this.getEffects().setTargetPointer(new FixedTarget(game.getCombat().getDefendingPlayerId(aura.getAttachedTo(), game)));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever enchanted creature attacks and isn't blocked, " + super.getRule();
return "Whenever enchanted creature attacks and isn't blocked, " +
"you may have it assign no combat damage this turn. " +
"If you do, defending player discards a card at random";
}
}
class CloakOfConfusionEffect extends OneShotEffect {
class CloakOfConfusionEffect extends ReplacementEffectImpl {
public CloakOfConfusionEffect() {
super(Outcome.Neutral);
this.staticText = "you may have it assign no combat damage this turn. "
+ "If you do, defending player discards a card at random";
CloakOfConfusionEffect() {
super(Duration.EndOfTurn, Outcome.Neutral);
}
public CloakOfConfusionEffect(final CloakOfConfusionEffect effect) {
private CloakOfConfusionEffect(final CloakOfConfusionEffect effect) {
super(effect);
}
@ -120,40 +106,6 @@ class CloakOfConfusionEffect extends OneShotEffect {
return new CloakOfConfusionEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent enchantedCreature = game.getPermanent(game.getPermanent(source.getSourceId()).getAttachedTo());
if (controller != null && controller.chooseUse(outcome, "Have defending player discard a card at random? " + enchantedCreature.getName() + " will not assign combat damage.", source, game)) {
ContinuousEffect effect = new AssignNoCombatDamageTargetEffect();
effect.setTargetPointer(new FixedTarget(enchantedCreature.getId()));
game.addEffect(effect, source);
Player defendingPlayer = game.getPlayer(targetPointer.getFirst(game, source));
if (defendingPlayer != null) {
defendingPlayer.discard(1, true, false, source, game);
}
return true;
}
return false;
}
}
class AssignNoCombatDamageTargetEffect extends ReplacementEffectImpl {
public AssignNoCombatDamageTargetEffect() {
super(Duration.EndOfTurn, Outcome.Neutral);
}
public AssignNoCombatDamageTargetEffect(final AssignNoCombatDamageTargetEffect effect) {
super(effect);
}
@Override
public AssignNoCombatDamageTargetEffect copy() {
return new AssignNoCombatDamageTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
@ -178,8 +130,10 @@ class AssignNoCombatDamageTargetEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
DamageEvent damageEvent = (DamageEvent) event;
return event.getSourceId().equals(targetPointer.getFirst(game, source))
&& damageEvent.isCombatDamage();
if (!((DamageEvent) event).isCombatDamage()) {
return false;
}
Permanent aura = source.getSourcePermanentOrLKI(game);
return aura != null && event.getSourceId().equals(aura.getAttachedTo());
}
}

View file

@ -1,46 +1,44 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
*
* @author MarcoMarin
*/
public final class DelifsCone extends CardImpl {
public DelifsCone(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{0}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}");
Ability ability2 = new AttacksAndIsNotBlockedTriggeredAbility(new DelifsConeEffect(), true);
ability2.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn));
// {tap}, Sacrifice Delif's Cone: This turn, when target creature you control attacks and isn't blocked, you may gain life equal to its power. If you do, it assigns no combat damage this turn.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new GainAbilityTargetEffect(ability2, Duration.EndOfTurn),
new TapSourceCost());
Ability ability = new SimpleActivatedAbility(
new CreateDelayedTriggeredAbilityEffect(
new DelifsConeTriggeredAbility(), false
), new TapSourceCost()
);
ability.addCost(new SacrificeSourceCost());
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
private DelifsCone(final DelifsCone card) {
@ -52,26 +50,106 @@ public final class DelifsCone extends CardImpl {
return new DelifsCone(this);
}
}
class DelifsConeEffect extends OneShotEffect{
public DelifsConeEffect() {
super(Outcome.Damage);
this.setText("you may gain life equal to its power");
class DelifsConeTriggeredAbility extends DelayedTriggeredAbility {
DelifsConeTriggeredAbility() {
super(new DelifsConeLifeEffect(), Duration.EndOfTurn, false, true);
this.addEffect(new DelifsConePreventEffect());
}
public DelifsConeEffect(final DelifsConeEffect effect) {
private DelifsConeTriggeredAbility(final DelifsConeTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getTargetId().equals(getFirstTarget());
}
@Override
public DelifsConeTriggeredAbility copy() {
return new DelifsConeTriggeredAbility(this);
}
@Override
public String getRule() {
return "This turn, when target creature you control attacks and isn't blocked, " +
"you may gain life equal to its power. If you do, it assigns no combat damage this turn.";
}
}
class DelifsConeLifeEffect extends OneShotEffect {
DelifsConeLifeEffect() {
super(Outcome.Benefit);
}
private DelifsConeLifeEffect(final DelifsConeLifeEffect effect) {
super(effect);
}
@Override
public DelifsConeEffect copy() {
return new DelifsConeEffect(this);
public DelifsConeLifeEffect copy() {
return new DelifsConeLifeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent perm = game.getPermanent(source.getSourceId());
GainLifeEffect lifeEffect = new GainLifeEffect(perm.getPower().getValue());
return lifeEffect.apply(game, source);
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
if (player != null || permanent != null) {
player.gainLife(permanent.getPower().getValue(), game, source);
return true;
}
return false;
}
}
}
class DelifsConePreventEffect extends ReplacementEffectImpl {
DelifsConePreventEffect() {
super(Duration.EndOfTurn, Outcome.Neutral);
}
private DelifsConePreventEffect(final DelifsConePreventEffect effect) {
super(effect);
}
@Override
public DelifsConePreventEffect copy() {
return new DelifsConePreventEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
return true;
default:
return false;
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return ((DamageEvent) event).isCombatDamage() && event.getTargetId().equals(targetPointer.getFirst(game, source));
}
}

View file

@ -1,55 +1,49 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.RegenerateTargetEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
*
* @author MarcoMarin
* @author TheElk801
*/
public final class DelifsCube extends CardImpl {
public DelifsCube(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
Ability ability2 = new AttacksAndIsNotBlockedTriggeredAbility(new DelifsCubeEffect(this.getId()), false);
ability2.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn));
// {2}, {tap}: This turn, when target creature you control attacks and isn't blocked, it assigns no combat damage this turn and you put a cube counter on Delif's Cube.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new GainAbilityTargetEffect(ability2, Duration.EndOfTurn),
new ManaCostsImpl("{2}"));
Ability ability = new SimpleActivatedAbility(
new CreateDelayedTriggeredAbilityEffect(new DelifsCubeTriggeredAbility()), new GenericManaCost(2)
);
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
// {2}, Remove a cube counter from Delif's Cube: Regenerate target creature.
SimpleActivatedAbility ability3 = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new RegenerateTargetEffect(),
new ManaCostsImpl("{2}"));
ability3.addCost(new RemoveCountersSourceCost(CounterType.CUBE.createInstance()));
ability3.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability3);
ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new GenericManaCost(2));
ability.addCost(new RemoveCountersSourceCost(CounterType.CUBE.createInstance()));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
private DelifsCube(final DelifsCube card) {
@ -62,31 +56,78 @@ public final class DelifsCube extends CardImpl {
}
}
class DelifsCubeEffect extends OneShotEffect{
private UUID cubeId;
public DelifsCubeEffect(UUID cubeId) {
super(Outcome.Benefit);
this.cubeId = cubeId;
this.setText("This turn, when target creature you control attacks and isn't blocked, it assigns no combat damage this turn and you put a cube counter on Delif's Cube");
class DelifsCubeTriggeredAbility extends DelayedTriggeredAbility {
DelifsCubeTriggeredAbility() {
super(new DelifsCubePreventEffect(), Duration.EndOfTurn, false, false);
this.addEffect(new AddCountersSourceEffect(CounterType.CUBE.createInstance()));
}
public DelifsCubeEffect(final DelifsCubeEffect effect) {
super(effect);
this.cubeId = effect.cubeId;
private DelifsCubeTriggeredAbility(final DelifsCubeTriggeredAbility ability) {
super(ability);
}
@Override
public DelifsCubeEffect copy() {
return new DelifsCubeEffect(this);
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getTargetId().equals(getFirstTarget());
}
@Override
public DelifsCubeTriggeredAbility copy() {
return new DelifsCubeTriggeredAbility(this);
}
@Override
public String getRule() {
return "This turn, when target creature you control attacks and isn't blocked, " +
"it assigns no combat damage this turn and you put a cube counter on {this}.";
}
}
class DelifsCubePreventEffect extends ReplacementEffectImpl {
DelifsCubePreventEffect() {
super(Duration.EndOfTurn, Outcome.Neutral);
}
private DelifsCubePreventEffect(final DelifsCubePreventEffect effect) {
super(effect);
}
@Override
public DelifsCubePreventEffect copy() {
return new DelifsCubePreventEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent perm = game.getPermanent(cubeId);
if (perm == null) return false;
perm.addCounters(CounterType.CUBE.createInstance(), source.getControllerId(), source, game);
return true;
return true;
}
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
return true;
default:
return false;
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return ((DamageEvent) event).isCombatDamage() && event.getTargetId().equals(targetPointer.getFirst(game, source));
}
}

View file

@ -1,38 +1,36 @@
package mage.cards.f;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author MarcoMarin
* @author TheElk801
*/
public final class FarrelsMantle extends CardImpl {
public FarrelsMantle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
this.subtype.add(SubType.AURA);
// Enchant creature
@ -41,17 +39,9 @@ public final class FarrelsMantle extends CardImpl {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Whenever enchanted creature attacks and isn't blocked, its controller may have it deal damage equal to its power plus 2 to another target creature. If that player does, the attacking creature assigns no combat damage this turn.
FilterPermanent filter = new FilterCreaturePermanent();
filter.add(Predicates.not(new AttachmentByUUIDPredicate(this.getId())));
Ability ability2 = new AttacksAndIsNotBlockedTriggeredAbility(new FarrelsMantleEffect(), true);
ability2.addTarget(new TargetPermanent(filter));
ability2.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ability2, AttachmentType.AURA)));
this.addAbility(new FarrelsMantleTriggeredAbility());
}
private FarrelsMantle(final FarrelsMantle card) {
@ -63,36 +53,69 @@ public final class FarrelsMantle extends CardImpl {
return new FarrelsMantle(this);
}
}
class AttachmentByUUIDPredicate implements Predicate<Permanent> {
private final UUID id;
class FarrelsMantleTriggeredAbility extends TriggeredAbilityImpl {
public AttachmentByUUIDPredicate(UUID id) {
this.id = id;
FarrelsMantleTriggeredAbility() {
super(Zone.BATTLEFIELD, null, false);
}
private FarrelsMantleTriggeredAbility(final FarrelsMantleTriggeredAbility ability) {
super(ability);
}
@Override
public boolean apply(Permanent input, Game game) {
return input.getAttachments().contains(id);
public FarrelsMantleTriggeredAbility copy() {
return new FarrelsMantleTriggeredAbility(this);
}
@Override
public String toString() {
return "AttachmentUUID(" + id + ')';
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent aura = getSourcePermanentOrLKI(game);
if (aura == null
|| !event.getTargetId().equals(aura.getAttachedTo())
|| game.getPermanent(aura.getAttachedTo()) == null) {
return false;
}
MageObjectReference mor = new MageObjectReference(event.getTargetId(), game);
FilterPermanent filter = new FilterCreaturePermanent();
filter.add(Predicates.not(new MageObjectReferencePredicate(mor)));
TargetPermanent target = new TargetPermanent(filter);
target.setTargetController(game.getControllerId(event.getTargetId()));
this.getTargets().clear();
this.addTarget(target);
this.getEffects().clear();
this.addEffect(new FarrelsMantleEffect(mor));
return true;
}
@Override
public String getRule() {
return "Whenever enchanted creature attacks and isn't blocked, its controller may have it deal damage " +
"equal to its power plus 2 to another target creature. If that player does, " +
"the attacking creature assigns no combat damage this turn.";
}
}
class FarrelsMantleEffect extends OneShotEffect{
public FarrelsMantleEffect() {
super(Outcome.Damage);
this.setText("its controller may have it deal damage equal to its power plus 2 to another target creature.");
class FarrelsMantleEffect extends OneShotEffect {
private final MageObjectReference mor;
FarrelsMantleEffect(MageObjectReference mor) {
super(Outcome.Benefit);
this.mor = mor;
}
public FarrelsMantleEffect(final FarrelsMantleEffect effect) {
private FarrelsMantleEffect(final FarrelsMantleEffect effect) {
super(effect);
this.mor = effect.mor;
}
@Override
public FarrelsMantleEffect copy() {
return new FarrelsMantleEffect(this);
@ -100,9 +123,67 @@ class FarrelsMantleEffect extends OneShotEffect{
@Override
public boolean apply(Game game, Ability source) {
Permanent perm = game.getPermanent(source.getSourceId());
int damage = CardUtil.overflowInc(perm.getPower().getValue(), 2);
DamageTargetEffect dmgEffect = new DamageTargetEffect(damage);
return dmgEffect.apply(game, source);
Permanent permanent = mor.getPermanent(game);
Permanent targeted = game.getPermanent(source.getFirstTarget());
if (permanent == null || targeted == null) {
return false;
}
int damage = permanent.getPower().getValue() + 2;
Player player = game.getPlayer(permanent.getControllerId());
if (damage > 0 && player != null && player.chooseUse(
outcome, "Have " + permanent.getIdName() + " deal "
+ damage + " to " + targeted.getIdName() + '?', source, game
) && targeted.damage(damage, permanent.getId(), source, game) > 0) {
game.addEffect(new FarrelsMantleDamageEffect(mor), source);
return true;
}
return false;
}
}
class FarrelsMantleDamageEffect extends ReplacementEffectImpl {
private final MageObjectReference mor;
FarrelsMantleDamageEffect(MageObjectReference mor) {
super(Duration.EndOfTurn, Outcome.Neutral);
this.mor = mor;
}
private FarrelsMantleDamageEffect(final FarrelsMantleDamageEffect effect) {
super(effect);
this.mor = effect.mor;
}
@Override
public FarrelsMantleDamageEffect copy() {
return new FarrelsMantleDamageEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
return true;
default:
return false;
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return ((DamageEvent) event).isCombatDamage() && mor.refersTo(event.getSourceId(), game);
}
}

View file

@ -1,23 +1,17 @@
package mage.cards.g;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -25,8 +19,9 @@ import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class GazeOfPain extends CardImpl {
@ -50,38 +45,29 @@ public final class GazeOfPain extends CardImpl {
class GazeOfPainDelayedTriggeredAbility extends DelayedTriggeredAbility {
Set<UUID> creatures = new HashSet<>();
public GazeOfPainDelayedTriggeredAbility() {
super(new GazeOfPainEffect(), Duration.EndOfTurn, false, true);
GazeOfPainDelayedTriggeredAbility() {
super(null, Duration.EndOfTurn, false, true);
this.addTarget(new TargetCreaturePermanent());
}
public GazeOfPainDelayedTriggeredAbility(GazeOfPainDelayedTriggeredAbility ability) {
private GazeOfPainDelayedTriggeredAbility(final GazeOfPainDelayedTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARE_BLOCKERS_STEP;
return event.getType() == GameEvent.EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getBlockers().isEmpty()) {
for (UUID attackerId : combatGroup.getAttackers()) {
if (game.getPermanent(attackerId).getControllerId() == controllerId
&& game.getPermanent(attackerId).isAttacking()) {
creatures.add(attackerId);
}
}
}
if (!isControlledBy(game.getControllerId(event.getTargetId()))) {
return false;
}
if (!creatures.isEmpty()) {
game.getState().setValue("gazeOfPain", creatures);
return true;
}
return false;
this.getEffects().clear();
this.addEffect(new GazeOfPainEffect(new MageObjectReference(event.getTargetId(), game)));
this.addEffect(new GazeOfPainDamageEffect().setTargetPointer(new FixedTarget(event.getTargetId(), game)));
return true;
}
@Override
@ -91,21 +77,24 @@ class GazeOfPainDelayedTriggeredAbility extends DelayedTriggeredAbility {
@Override
public String getRule() {
return "Until end of turn, whenever a creature you control attacks and isn't blocked, " + super.getRule();
return "Until end of turn, whenever a creature you control attacks and isn't blocked, " +
"you may choose to have it deal damage equal to its power to a target creature. " +
"If you do, it assigns no combat damage this turn.";
}
}
class GazeOfPainEffect extends OneShotEffect {
Set<UUID> creatures = new HashSet<>();
private final MageObjectReference mor;
GazeOfPainEffect() {
GazeOfPainEffect(MageObjectReference mor) {
super(Outcome.Benefit);
this.staticText = "you may choose to have it deal damage equal to its power to a target creature. If you do, it assigns no combat damage this turn.";
this.mor = mor;
}
GazeOfPainEffect(final GazeOfPainEffect effect) {
private GazeOfPainEffect(final GazeOfPainEffect effect) {
super(effect);
this.mor = effect.mor;
}
@Override
@ -115,46 +104,29 @@ class GazeOfPainEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
creatures = (Set<UUID>) game.getState().getValue("gazeOfPain");
if (!creatures.isEmpty()) {
for (UUID attackerId : creatures) {
Permanent attacker = game.getPermanent(attackerId);
if (controller != null
&& attacker != null) {
if (controller.chooseUse(outcome, "Do you wish to deal damage equal to " + attacker.getName() + "'s power to a target creature?", source, game)) {
TargetCreaturePermanent target = new TargetCreaturePermanent();
if (target.canChoose(source.getSourceId(), controller.getId(), game)
&& controller.choose(Outcome.Detriment, target, source.getSourceId(), game)) {
Effect effect = new DamageTargetEffect(attacker.getPower().getValue());
effect.setTargetPointer(new FixedTarget(target.getFirstTarget()));
effect.apply(game, source);
ContinuousEffect effect2 = new AssignNoCombatDamageTargetEffect();
effect2.setTargetPointer(new FixedTarget(attackerId));
game.addEffect(effect2, source);
}
}
}
}
return true;
}
return false;
Player player = game.getPlayer(source.getControllerId());
Permanent creature = mor.getPermanent(game);
Permanent targeted = game.getPermanent(source.getFirstTarget());
return player != null
&& creature != null
&& targeted != null
&& targeted.damage(creature.getPower().getValue(), creature.getId(), source, game) > 0;
}
}
class AssignNoCombatDamageTargetEffect extends ReplacementEffectImpl {
class GazeOfPainDamageEffect extends ReplacementEffectImpl {
public AssignNoCombatDamageTargetEffect() {
GazeOfPainDamageEffect() {
super(Duration.EndOfTurn, Outcome.Neutral);
}
public AssignNoCombatDamageTargetEffect(final AssignNoCombatDamageTargetEffect effect) {
private GazeOfPainDamageEffect(final GazeOfPainDamageEffect effect) {
super(effect);
}
@Override
public AssignNoCombatDamageTargetEffect copy() {
return new AssignNoCombatDamageTargetEffect(this);
public GazeOfPainDamageEffect copy() {
return new GazeOfPainDamageEffect(this);
}
@Override
@ -181,8 +153,6 @@ class AssignNoCombatDamageTargetEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
DamageEvent damageEvent = (DamageEvent) event;
return event.getSourceId().equals(targetPointer.getFirst(game, source))
&& damageEvent.isCombatDamage();
return ((DamageEvent) event).isCombatDamage() && event.getSourceId().equals(targetPointer.getFirst(game, source));
}
}

View file

@ -1,12 +1,8 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.keyword.ProwlAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -16,13 +12,14 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author BursegSardaukar
*/
public final class StinkdrinkerBandit extends CardImpl {
@ -45,9 +42,7 @@ public final class StinkdrinkerBandit extends CardImpl {
this.addAbility(new ProwlAbility(this, "{1}{B}"));
// Whenever a Rogue you control attacks and isn't blocked, it gets +2/+1 until end of turn.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(
new StinkdrinkerBanditTriggeredAbility(), Duration.WhileOnBattlefield,
filter, "Whenever a Rogue you control attacks and isn't blocked, it gets +2/+1 until end of turn")));
this.addAbility(new StinkdrinkerBanditTriggeredAbility());
}
private StinkdrinkerBandit(final StinkdrinkerBandit card) {
@ -62,11 +57,11 @@ public final class StinkdrinkerBandit extends CardImpl {
class StinkdrinkerBanditTriggeredAbility extends TriggeredAbilityImpl {
public StinkdrinkerBanditTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(2, 1, Duration.EndOfTurn));
StinkdrinkerBanditTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostTargetEffect(2, 1, Duration.EndOfTurn));
}
public StinkdrinkerBanditTriggeredAbility(final StinkdrinkerBanditTriggeredAbility ability) {
private StinkdrinkerBanditTriggeredAbility(final StinkdrinkerBanditTriggeredAbility ability) {
super(ability);
}
@ -77,20 +72,17 @@ class StinkdrinkerBanditTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_BLOCKERS;
return event.getType() == EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent sourcePermanent = game.getPermanent(getSourceId());
if (sourcePermanent.isAttacking()) {
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getBlockers().isEmpty()
&& combatGroup.getDefenderId().equals(event.getTargetId())
&& combatGroup.getAttackers().contains(getSourceId())) {
return true;
}
}
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null
&& isControlledBy(permanent.getControllerId())
&& permanent.hasSubtype(SubType.ROGUE, game)) {
getEffects().setTargetPointer(new FixedTarget(permanent, game));
return true;
}
return false;
}

View file

@ -1,14 +1,11 @@
package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
public class AttacksAndIsNotBlockedTriggeredAbility extends TriggeredAbilityImpl {
@ -40,23 +37,20 @@ public class AttacksAndIsNotBlockedTriggeredAbility extends TriggeredAbilityImpl
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARE_BLOCKERS_STEP;
return event.getType() == EventType.UNBLOCKED_ATTACKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId());
if (sourcePermanent != null && sourcePermanent.isAttacking()) {
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(getSourceId())) {
if (setTargetPointer) {
this.getEffects().setTargetPointer(new FixedTarget(game.getCombat().getDefendingPlayerId(getSourceId(), game)));
}
return true;
}
}
if (!event.getTargetId().equals(getSourceId())) {
return false;
}
return false;
if (setTargetPointer) {
this.getEffects().setTargetPointer(new FixedTarget(
game.getCombat().getDefendingPlayerId(getSourceId(), game), game
));
}
return true;
}
@Override