updated implementation of abilities which trigger on gaining life for the first time in a turn

This commit is contained in:
Evan Kranzler 2020-09-23 19:53:09 -04:00
parent b7e5d44b9d
commit be3834e762
4 changed files with 121 additions and 156 deletions

View file

@ -2,7 +2,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.GainLifeFirstTimeTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
@ -13,11 +13,8 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.CatToken3;
import mage.target.TargetPermanent;
@ -43,7 +40,7 @@ public final class AttendedHealer extends CardImpl {
this.toughness = new MageInt(3);
// Whenever you gain life for the first time each turn, create a 1/1 white Cat creature token.
this.addAbility(new AttendedHealerTriggeredAbility());
this.addAbility(new GainLifeFirstTimeTriggeredAbility(new CreateTokenEffect(new CatToken3())));
// {2}{W}: Another target Cleric gains lifelink until end of turn.
Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(
@ -63,50 +60,3 @@ public final class AttendedHealer extends CardImpl {
return new AttendedHealer(this);
}
}
class AttendedHealerTriggeredAbility extends TriggeredAbilityImpl {
private boolean triggeredOnce = false;
AttendedHealerTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new CatToken3()), false);
}
private AttendedHealerTriggeredAbility(final AttendedHealerTriggeredAbility ability) {
super(ability);
this.triggeredOnce = ability.triggeredOnce;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.GAINED_LIFE
|| event.getType() == GameEvent.EventType.END_PHASE_POST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.END_PHASE_POST) {
triggeredOnce = false;
return false;
}
if (event.getType() != GameEvent.EventType.GAINED_LIFE
|| !event.getPlayerId().equals(getControllerId())) {
return false;
}
if (triggeredOnce) {
return false;
}
triggeredOnce = true;
return true;
}
@Override
public String getRule() {
return "Whenever you gain life for the first time each turn, create a 1/1 white Cat creature token.";
}
@Override
public AttendedHealerTriggeredAbility copy() {
return new AttendedHealerTriggeredAbility(this);
}
}

View file

@ -1,21 +1,18 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.GainLifeFirstTimeTriggeredAbility;
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.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import java.util.UUID;
@ -44,7 +41,9 @@ public final class ClericOfLifesBond extends CardImpl {
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new GainLifeEffect(1), filter));
// Whenever you gain life for the first time each turn, put a +1/+1 counter on Cleric of Lifes Bond.
this.addAbility(new ClericOfLifesBondCounterTriggeredAbility());
this.addAbility(new GainLifeFirstTimeTriggeredAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance())
));
}
@ -57,50 +56,3 @@ public final class ClericOfLifesBond extends CardImpl {
return new ClericOfLifesBond(this);
}
}
class ClericOfLifesBondCounterTriggeredAbility extends TriggeredAbilityImpl {
private boolean triggeredOnce = false;
ClericOfLifesBondCounterTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false);
}
private ClericOfLifesBondCounterTriggeredAbility(final ClericOfLifesBondCounterTriggeredAbility ability) {
super(ability);
this.triggeredOnce = ability.triggeredOnce;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.GAINED_LIFE
|| event.getType() == GameEvent.EventType.END_PHASE_POST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.END_PHASE_POST) {
triggeredOnce = false;
return false;
}
if (event.getType() != GameEvent.EventType.GAINED_LIFE
|| !event.getPlayerId().equals(getControllerId())) {
return false;
}
if (triggeredOnce) {
return false;
}
triggeredOnce = true;
return true;
}
@Override
public String getRule() {
return "Whenever you gain life for the first time each turn, put a +1/+1 counter on {this}.";
}
@Override
public ClericOfLifesBondCounterTriggeredAbility copy() {
return new ClericOfLifesBondCounterTriggeredAbility(this);
}
}

View file

@ -1,8 +1,7 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.GainLifeFirstTimeTriggeredAbility;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
@ -10,8 +9,8 @@ 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 java.util.UUID;
/**
* @author TheElk801
@ -30,7 +29,9 @@ public final class DeathlessKnight extends CardImpl {
this.addAbility(HasteAbility.getInstance());
// When you gain life for the first time each turn, return Deathless Knight from your graveyard to your hand.
this.addAbility(new DeathlessKnightTriggeredAbility());
this.addAbility(new GainLifeFirstTimeTriggeredAbility(
Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), false, true
));
}
private DeathlessKnight(final DeathlessKnight card) {
@ -42,50 +43,3 @@ public final class DeathlessKnight extends CardImpl {
return new DeathlessKnight(this);
}
}
class DeathlessKnightTriggeredAbility extends TriggeredAbilityImpl {
private boolean triggeredOnce = false;
DeathlessKnightTriggeredAbility() {
super(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), false);
}
private DeathlessKnightTriggeredAbility(final DeathlessKnightTriggeredAbility ability) {
super(ability);
this.triggeredOnce = ability.triggeredOnce;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.GAINED_LIFE
|| event.getType() == GameEvent.EventType.END_PHASE_POST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.END_PHASE_POST) {
triggeredOnce = false;
return false;
}
if (event.getType() != GameEvent.EventType.GAINED_LIFE
|| !event.getPlayerId().equals(getControllerId())) {
return false;
}
if (triggeredOnce) {
return false;
}
triggeredOnce = true;
return true;
}
@Override
public String getRule() {
return "When you gain life for the first time each turn, return {this} from your graveyard to your hand.";
}
@Override
public DeathlessKnightTriggeredAbility copy() {
return new DeathlessKnightTriggeredAbility(this);
}
}

View file

@ -0,0 +1,109 @@
package mage.abilities.common;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.condition.Condition;
import mage.abilities.effects.Effect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
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;
/**
* @author TheElk801
*/
public class GainLifeFirstTimeTriggeredAbility extends TriggeredAbilityImpl {
private static final Hint hint = new ConditionHint(GainLifeCondition.instance);
private final boolean when;
public GainLifeFirstTimeTriggeredAbility(Effect effect) {
this(Zone.BATTLEFIELD, effect, false, false);
}
public GainLifeFirstTimeTriggeredAbility(Zone zone, Effect effect, boolean optional, boolean when) {
super(zone, effect, optional);
this.when = when;
this.addWatcher(new GainLifeFirstTimeWatcher());
}
private GainLifeFirstTimeTriggeredAbility(final GainLifeFirstTimeTriggeredAbility ability) {
super(ability);
this.when = ability.when;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.GAINED_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
GainLifeFirstTimeWatcher watcher = game.getState().getWatcher(GainLifeFirstTimeWatcher.class);
return watcher != null && watcher.checkEvent(getControllerId(), event);
}
@Override
public String getRule() {
return "When" + (when ? "" : "ever") + " you gain life for the first time each turn, " + super.getRule();
}
@Override
public GainLifeFirstTimeTriggeredAbility copy() {
return new GainLifeFirstTimeTriggeredAbility(this);
}
}
enum GainLifeCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
GainLifeFirstTimeWatcher watcher = game.getState().getWatcher(GainLifeFirstTimeWatcher.class);
return watcher != null && watcher.checkGain(source.getControllerId());
}
@Override
public String toString() {
return "You haven't gained life this turn";
}
}
class GainLifeFirstTimeWatcher extends Watcher {
private final Map<UUID, UUID> gainedMap = new HashMap<>();
GainLifeFirstTimeWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.GAINED_LIFE
|| event.getAmount() < 1) {
return;
}
gainedMap.putIfAbsent(event.getPlayerId(), event.getId());
}
@Override
public void reset() {
super.reset();
gainedMap.clear();
}
boolean checkEvent(UUID playerId, GameEvent event) {
return event.getId().equals(gainedMap.getOrDefault(playerId, null));
}
boolean checkGain(UUID playerId) {
return !gainedMap.containsKey(playerId);
}
}