From f33d9006c680466b6947394aa8a35276d16df577 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 21 Aug 2017 11:29:34 -0400 Subject: [PATCH] Implemented Mairsil but this is possibly game-breaking --- .../src/mage/cards/m/MairsilThePretender.java | 7 +- .../mage/abilities/ActivatedAbilityImpl.java | 141 ++++++++++++------ 2 files changed, 103 insertions(+), 45 deletions(-) diff --git a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java index 74d3bb2e992..7ee0d818646 100644 --- a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java +++ b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java @@ -31,8 +31,8 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; +import mage.abilities.ActivatedAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; @@ -102,7 +102,7 @@ class MairsilThePretenderExileEffect extends OneShotEffect { MairsilThePretenderExileEffect() { super(Outcome.Benefit); - this.staticText = ""; + this.staticText = "you may exile an artifact or creature card from your hand or graveyard and put a cage counter on it."; } MairsilThePretenderExileEffect(final MairsilThePretenderExileEffect effect) { @@ -167,7 +167,8 @@ class MairsilThePretenderGainAbilitiesEffect extends ContinuousEffectImpl { if (filter.match(card, game)) { for (Ability ability : card.getAbilities()) { if (ability instanceof ActivatedAbility) { - ActivatedAbility copyAbility = (ActivatedAbility) ability.copy(); + ActivatedAbilityImpl copyAbility = (ActivatedAbilityImpl) ability; + copyAbility.setMaxActivationsPerTurn(1); perm.addAbility(copyAbility, card.getId(), game); } } diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 5021a83896f..eb05b059e59 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -45,6 +45,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.command.Emblem; import mage.game.permanent.Permanent; +import mage.util.CardUtil; /** * @@ -52,10 +53,22 @@ import mage.game.permanent.Permanent; */ public abstract class ActivatedAbilityImpl extends AbilityImpl implements ActivatedAbility { + static class ActivationInfo { + + public int turnNum; + public int activationCounter; + + public ActivationInfo(int turnNum, int activationCounter) { + this.turnNum = turnNum; + this.activationCounter = activationCounter; + } + } + protected TimingRule timing = TimingRule.INSTANT; protected TargetController mayActivate = TargetController.YOU; protected UUID activatorId; protected boolean checkPlayableMode; + private int maxActivationsPerTurn; protected ActivatedAbilityImpl(AbilityType abilityType, Zone zone) { super(abilityType, zone); @@ -159,55 +172,82 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa public abstract ActivatedAbilityImpl copy(); @Override - public boolean canActivate(UUID playerId, Game game) { - //20091005 - 602.2 - switch (mayActivate) { - case ANY: - break; - - case NOT_YOU: - if (controlsAbility(playerId, game)) { - return false; + public boolean activate(Game game, boolean noMana) { + if (hasMoreActivationsThisTurn(game)) { + if (super.activate(game, noMana)) { + ActivatedAbilityImpl.ActivationInfo activationInfo = getActivationInfo(game); + if (activationInfo == null) { + activationInfo = new ActivatedAbilityImpl.ActivationInfo(game.getTurnNum(), 1); + } else if (activationInfo.turnNum != game.getTurnNum()) { + activationInfo.turnNum = game.getTurnNum(); + activationInfo.activationCounter = 1; + } else { + activationInfo.activationCounter++; } - break; - - case OPPONENT: - if (!game.getPlayer(controllerId).hasOpponent(playerId, game)) { - return false; - } - break; - case OWNER: - Permanent permanent = game.getPermanent(getSourceId()); - if (!permanent.getOwnerId().equals(playerId)) { - return false; - } - break; - case YOU: - if (!controlsAbility(playerId, game)) { - return false; - } - break; - case CONTROLLER_ATTACHED_TO: - Permanent enchantment = game.getPermanent(getSourceId()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); - if (enchanted != null && enchanted.getControllerId().equals(playerId)) { - break; - } - } - return false; - } - //20091005 - 602.5d/602.5e - if (timing == TimingRule.INSTANT || game.canPlaySorcery(playerId) - || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) { - if (costs.canPay(this, sourceId, playerId, game) && canChooseTarget(game)) { - this.activatorId = playerId; + setActivationInfo(activationInfo, game); return true; } } return false; } + @Override + public boolean canActivate(UUID playerId, Game game) { + //20091005 - 602.2 + if (hasMoreActivationsThisTurn(game)) { + switch (mayActivate) { + case ANY: + break; + + case NOT_YOU: + if (controlsAbility(playerId, game)) { + return false; + } + break; + + case OPPONENT: + if (!game.getPlayer(controllerId).hasOpponent(playerId, game)) { + return false; + } + break; + case OWNER: + Permanent permanent = game.getPermanent(getSourceId()); + if (!permanent.getOwnerId().equals(playerId)) { + return false; + } + break; + case YOU: + if (!controlsAbility(playerId, game)) { + return false; + } + break; + case CONTROLLER_ATTACHED_TO: + Permanent enchantment = game.getPermanent(getSourceId()); + if (enchantment != null && enchantment.getAttachedTo() != null) { + Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); + if (enchanted != null && enchanted.getControllerId().equals(playerId)) { + break; + } + } + return false; + } + //20091005 - 602.5d/602.5e + if (timing == TimingRule.INSTANT || game.canPlaySorcery(playerId) + || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) { + if (costs.canPay(this, sourceId, playerId, game) && canChooseTarget(game)) { + this.activatorId = playerId; + return true; + } + } + } + return false; + } + + private boolean hasMoreActivationsThisTurn(Game game) { + ActivatedAbilityImpl.ActivationInfo activationInfo = this.getActivationInfo(game); + return activationInfo == null || activationInfo.turnNum != game.getTurnNum() || activationInfo.activationCounter < maxActivationsPerTurn; + } + @Override public ManaOptions getMinimumCostToActivate(UUID playerId, Game game) { return getManaCostsToPay().getOptions(); @@ -255,4 +295,21 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa return checkPlayableMode; } + public void setMaxActivationsPerTurn(int maxActivationsPerTurn) { + this.maxActivationsPerTurn = maxActivationsPerTurn; + } + + private ActivatedAbilityImpl.ActivationInfo getActivationInfo(Game game) { + Integer turnNum = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsTurn"+this.getOriginalId().toString(), sourceId, game)); + Integer activationCount = (Integer) game.getState().getValue(CardUtil.getCardZoneString("activationsCount"+this.getOriginalId().toString(), sourceId, game)); + if (turnNum == null || activationCount == null) { + return null; + } + return new ActivatedAbilityImpl.ActivationInfo(turnNum, activationCount); + } + + private void setActivationInfo(ActivatedAbilityImpl.ActivationInfo activationInfo, Game game) { + game.getState().setValue(CardUtil.getCardZoneString("activationsTurn"+this.getOriginalId().toString(), sourceId, game), activationInfo.turnNum); + game.getState().setValue(CardUtil.getCardZoneString("activationsCount"+this.getOriginalId().toString(), sourceId, game), activationInfo.activationCounter); + } }