Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unbound Flourishing's X doubling should be a triggered ability (and related refactors) #12597

Merged
merged 16 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.AbilityImpl;
import mage.abilities.ActivatedAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.PassAbility;
Expand Down Expand Up @@ -154,12 +153,8 @@ protected void addVariableXOptions(List<Ability> options, Ability ability, int t
}
}
// find real X value after replace events
int xMultiplier = 1;
if (newAbility instanceof AbilityImpl) {
xMultiplier = ((AbilityImpl) newAbility).handleManaXMultiplier(game, xMultiplier);
}
newAbility.addManaCostsToPay(new ManaCostsImpl<>(new StringBuilder("{").append(xAnnounceValue).append('}').toString()));
newAbility.getManaCostsToPay().setX(xAnnounceValue * xMultiplier, xAnnounceValue * xInstancesCount);
newAbility.getManaCostsToPay().setX(xAnnounceValue, xAnnounceValue * xInstancesCount);
if (varCost != null) {
varCost.setPaid();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1921,20 +1921,18 @@ public int compare(Entry<MageObject, Integer> o1, Entry<MageObject, Integer> o2)
}

@Override
public int announceXMana(int min, int max, int multiplier, String message, Game game, Ability ability) {
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
log.debug("announceXMana");
//TODO: improve this
int xMin = min * multiplier;
int xMax = (max == Integer.MAX_VALUE ? max : max * multiplier);
int numAvailable = getAvailableManaProducers(game).size() - ability.getManaCosts().manaValue();
if (numAvailable < 0) {
numAvailable = 0;
} else {
if (numAvailable < xMin) {
numAvailable = xMin;
if (numAvailable < min) {
numAvailable = min;
}
if (numAvailable > xMax) {
numAvailable = xMax;
if (numAvailable > max) {
numAvailable = max;
}
}
return numAvailable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1668,24 +1668,22 @@ public int announceRepetitions(Game game) {
*
* @param min
* @param max
* @param multiplier - X multiplier after replace events
* @param message
* @param ability
* @param game
* @return
*/
@Override
public int announceXMana(int min, int max, int multiplier, String message, Game game, Ability ability) {
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
if (gameInCheckPlayableState(game)) {
return 0;
}

int xValue = 0;
String extraMessage = (multiplier == 1 ? "" : ", X will be increased by " + multiplier + " times");
while (canRespond()) {
prepareForResponse(game);
if (!isExecutingMacro()) {
game.fireGetAmountEvent(playerId, message + extraMessage + CardUtil.getSourceLogName(game, ability), min, max);
game.fireGetAmountEvent(playerId, message + CardUtil.getSourceLogName(game, ability), min, max);
}
waitForResponse(game);

Expand Down
4 changes: 2 additions & 2 deletions Mage.Sets/src/mage/cards/a/AbolethSpawn.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.target.targetpointer.FixedTarget;

import java.util.UUID;

Expand Down Expand Up @@ -92,8 +93,7 @@ public boolean checkTrigger(GameEvent event, Game game) {
if (triggerEvent.getSourceId() != permanent.getId()) {
return false; // only triggered abilities of that creature
}
// CopyStackObjectEffect needs value set
getEffects().setValue("stackObject", stackObject);
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}

Expand Down
12 changes: 4 additions & 8 deletions Mage.Sets/src/mage/cards/a/AshnodTheUncaring.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.target.targetpointer.FixedTarget;

import java.util.UUID;

Expand Down Expand Up @@ -53,6 +54,8 @@ class AshnodTheUncaringTriggeredAbility extends TriggeredAbilityImpl {

AshnodTheUncaringTriggeredAbility() {
super(Zone.BATTLEFIELD, new CopyStackObjectEffect(), true);
setTriggerPhrase("Whenever you activate an ability of an artifact or creature that isn't a mana ability, " +
"if one or more permanents were sacrificed to activate it, ");
}

private AshnodTheUncaringTriggeredAbility(final AshnodTheUncaringTriggeredAbility ability) {
Expand Down Expand Up @@ -88,14 +91,7 @@ public boolean checkTrigger(GameEvent event, Game game) {
if (permanent == null || (!permanent.isArtifact(game) && !permanent.isCreature(game))) {
return false;
}
this.getEffects().setValue("stackObject", stackAbility);
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}

@Override
public String getRule() {
return "Whenever you activate an ability of an artifact or creature that isn't a mana ability, " +
"if one or more permanents were sacrificed to activate it, " +
"you may copy that ability. You may choose new targets for the copy.";
}
}
61 changes: 14 additions & 47 deletions Mage.Sets/src/mage/cards/b/BattlemagesBracers.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package mage.cards.b;

import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.ActivateAbilityTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CopyStackObjectEffect;
Expand All @@ -11,10 +11,10 @@
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.filter.FilterStackObject;
import mage.filter.common.FilterActivatedOrTriggeredAbility;
import mage.filter.predicate.other.AbilitySourceAttachedPredicate;
import mage.filter.predicate.other.NotManaAbilityPredicate;
import mage.target.common.TargetControlledCreaturePermanent;

import java.util.UUID;
Expand All @@ -24,6 +24,13 @@
*/
public final class BattlemagesBracers extends CardImpl {

private static final FilterStackObject filter = new FilterActivatedOrTriggeredAbility("an ability of equipped creature");

static {
filter.add(NotManaAbilityPredicate.instance);
filter.add(AbilitySourceAttachedPredicate.instance);
}

public BattlemagesBracers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}");

Expand All @@ -35,7 +42,8 @@ public BattlemagesBracers(UUID ownerId, CardSetInfo setInfo) {
)));

// Whenever an ability of equipped creature is activated, if it isn't a mana ability, you may pay {1}. If you do, copy that ability. You may choose new targets for the copy.
this.addAbility(new BattlemagesBracersTriggeredAbility());
this.addAbility(new ActivateAbilityTriggeredAbility(new DoIfCostPaid(new CopyStackObjectEffect(), new GenericManaCost(1)), filter, SetTargetPointer.SPELL)
.setTriggerPhrase("Whenever an ability of equipped creature is activated, if it isn't a mana ability, "));

// Equip {2}
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2), new TargetControlledCreaturePermanent(), false));
Expand All @@ -50,44 +58,3 @@ public BattlemagesBracers copy() {
return new BattlemagesBracers(this);
}
}

class BattlemagesBracersTriggeredAbility extends TriggeredAbilityImpl {

BattlemagesBracersTriggeredAbility() {
super(Zone.BATTLEFIELD, new DoIfCostPaid(new CopyStackObjectEffect(), new GenericManaCost(1)));
}

private BattlemagesBracersTriggeredAbility(final BattlemagesBracersTriggeredAbility ability) {
super(ability);
}

@Override
public BattlemagesBracersTriggeredAbility copy() {
return new BattlemagesBracersTriggeredAbility(this);
}

@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(this.getSourceId());
if (equipment == null || !equipment.isAttachedTo(event.getSourceId())) {
return false;
}
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
if (stackAbility == null || stackAbility.getStackAbility().isManaActivatedAbility()) {
return false;
}
getEffects().setValue("stackObject", stackAbility);
return true;
}

@Override
public String getRule() {
return "Whenever an ability of equipped creature is activated, if it isn't a mana ability, you may pay {1}. " +
"If you do, copy that ability. You may choose new targets for the copy.";
}
}
3 changes: 2 additions & 1 deletion Mage.Sets/src/mage/cards/b/BreechesTheBlastmaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.target.targetpointer.FixedTarget;

import java.util.Optional;
import java.util.UUID;
Expand Down Expand Up @@ -87,7 +88,7 @@ public boolean apply(Game game, Ability source) {
if (player.flipCoin(source, game, true)) {
Effect effect = new CopyStackObjectEffect();
effect.setText("copy that spell. You may choose new targets for the copy");
effect.setValue("stackObject", spell);
effect.setTargetPointer(new FixedTarget(spell.getId(), game));
ability = new ReflexiveTriggeredAbility(effect, false);
} else {
int mv = Optional
Expand Down
58 changes: 9 additions & 49 deletions Mage.Sets/src/mage/cards/c/ChandrasRegulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CopyStackObjectEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.players.Player;
import mage.target.common.TargetCardInHand;

import java.util.UUID;
Expand All @@ -44,7 +44,9 @@ public ChandrasRegulator(UUID ownerId, CardSetInfo setInfo) {
this.supertype.add(SuperType.LEGENDARY);

// Whenever you activate a loyalty ability of a Chandra planeswalker, you may pay {1}. If you do, copy that ability. You may choose new targets for the copy.
this.addAbility(new ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility(new ChandrasRegulatorEffect(), SubType.CHANDRA));
this.addAbility(new ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility(
new DoIfCostPaid(new CopyStackObjectEffect(), new ManaCostsImpl<>("{1}")),
SubType.CHANDRA, SetTargetPointer.SPELL));

// {1}, {T}, Discard a Mountain card or a red card: Draw a card.
Ability ability = new SimpleActivatedAbility(
Expand All @@ -64,45 +66,3 @@ public ChandrasRegulator copy() {
return new ChandrasRegulator(this);
}
}

class ChandrasRegulatorEffect extends OneShotEffect {

ChandrasRegulatorEffect() {
super(Outcome.Benefit);
staticText = "you may pay {1}. If you do, copy that ability. You may choose new targets for the copy";
}

private ChandrasRegulatorEffect(final ChandrasRegulatorEffect effect) {
super(effect);
}

@Override
public ChandrasRegulatorEffect copy() {
return new ChandrasRegulatorEffect(this);
}

@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
ManaCostsImpl cost = new ManaCostsImpl<>("{1}");
if (player == null) {
return false;
}
if (!cost.canPay(source, source, player.getId(), game)
|| !player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() +
"? If you do, copy that ability. You may choose new targets for the copy.", source, game)) {
return true;
}
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
return true;
}
StackAbility ability = (StackAbility) getValue("stackObject");
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (ability == null || controller == null || sourcePermanent == null) {
return false;
}
ability.createCopyOnStack(game, source, source.getControllerId(), true);
return true;
}
}
10 changes: 3 additions & 7 deletions Mage.Sets/src/mage/cards/d/DynaheirInvokerAdept.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.ManaPaidSourceWatcher;

import java.util.UUID;
Expand Down Expand Up @@ -91,6 +92,7 @@ class DynaheirInvokerAdeptTriggeredAbility extends DelayedTriggeredAbility {

DynaheirInvokerAdeptTriggeredAbility() {
super(new CopyStackObjectEffect(), Duration.EndOfTurn, true);
setTriggerPhrase("When you next activate an ability that isn't a mana ability this turn by spending four or more mana to activate it, ");
}

private DynaheirInvokerAdeptTriggeredAbility(final DynaheirInvokerAdeptTriggeredAbility ability) {
Expand Down Expand Up @@ -118,13 +120,7 @@ public boolean checkTrigger(GameEvent event, Game game) {
|| ManaPaidSourceWatcher.getTotalPaid(stackAbility.getId(), game) < 4) {
return false;
}
this.getEffects().setValue("stackObject", stackAbility);
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}

@Override
public String getRule() {
return "When you next activate an ability that isn't a mana ability this turn by spending four or more mana to activate it, " +
"copy that ability. You may choose new targets for the copy.";
}
}
7 changes: 2 additions & 5 deletions Mage.Sets/src/mage/cards/e/ErthaJoFrontierMentor.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@
import mage.filter.FilterPlayer;
import mage.filter.FilterStackObject;
import mage.filter.StaticFilters;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.mageobject.TargetsPermanentOrPlayerPredicate;
import mage.filter.predicate.mageobject.TargetsPermanentPredicate;
import mage.filter.predicate.mageobject.TargetsPlayerPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.MercenaryToken;
import mage.game.stack.StackObject;
import mage.target.targetpointer.FixedTarget;

import java.util.UUID;

Expand Down Expand Up @@ -94,7 +91,7 @@ public boolean checkTrigger(GameEvent event, Game game) {
return false;
}
// For the copy effect to find.
this.getEffects().setValue("stackObject", stackObject);
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}
}
Loading
Loading