From 3e498e23e6373853826d4375bddbf9b3aef99ecd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 12 Aug 2020 16:26:22 +0200 Subject: [PATCH] * Offering ability - Fixed use in available mana calculation (related to #6698). --- .../abilities/keywords/OfferingTest.java | 29 +++++++++++- .../abilities/keyword/OfferingAbility.java | 45 +++++++++++++++++-- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/OfferingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/OfferingTest.java index 37c9d12e65..ec9d083bb6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/OfferingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/OfferingTest.java @@ -46,6 +46,33 @@ public class OfferingTest extends CardTestPlayerBase { assertPermanentCount(playerA, kurosTaken, 1); assertPermanentCount(playerA, nezumiPatron, 1); - assertTappedCount("Swamp", true, 7); // {5}{B}{B} - {1}{B} = {4}{B} = 7 swamps tapped + assertTappedCount("Swamp", true, 7); // {5}{B}{B} - {1}{B} = {4}{B} = 7 swamps tapped } + + @Test + public void testCastWithMinimalMana() { + setStrictChooseMode(true); + + // Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.) + // Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn. + String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5) + + addCard(Zone.HAND, playerA, patron, 1); + + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.BATTLEFIELD, playerA, "Akki Drillmaster"); // Creature Goblin {2}{R} (2/2) + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron); + setChoice(playerA, "Yes"); + addTarget(playerA, "Akki Drillmaster"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertAllCommandsUsed(); + assertPermanentCount(playerA, patron, 1); + + assertGraveyardCount(playerA, "Akki Drillmaster", 1); + + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java index da1c503eb6..a13f0671db 100644 --- a/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/OfferingAbility.java @@ -1,14 +1,26 @@ package mage.abilities.keyword; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; +import mage.Mana; +import mage.ObjectColor; import mage.abilities.Ability; +import mage.abilities.SpecialAction; import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; +import mage.abilities.costs.mana.ActivationManaAbilityStep; +import mage.abilities.costs.mana.AlternateManaPaymentAbility; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.mana.ManaOptions; import mage.cards.Card; import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -39,7 +51,7 @@ import mage.util.GameLog; * * @author LevelX2 */ -public class OfferingAbility extends StaticAbility { +public class OfferingAbility extends StaticAbility implements AlternateManaPaymentAbility { private FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); @@ -72,6 +84,31 @@ public class OfferingAbility extends StaticAbility { String subtype = filter.getMessage(); return subtype + " offering (You may cast this card any time you could cast an instant by sacrificing a " + subtype + " and paying the difference in mana costs between this and the sacrificed " + subtype + ". Mana cost includes color.)"; } + + @Override + public ActivationManaAbilityStep useOnActivationManaAbilityStep() { + return ActivationManaAbilityStep.NORMAL; + } + + @Override + public void addSpecialAction(Ability source, Game game, ManaCost unpaid) { + // No special Action + } + + @Override + public ManaOptions getManaOptions(Ability source, Game game, ManaCost unpaid) { + ManaOptions options = new ManaOptions(); + + // Creatures from the offerd type + game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game) + .stream() + .forEach(permanent -> { + options.addMana(permanent.getSpellAbility().getManaCosts().getMana()); + }); + + options.removeDuplicated(); + return options; + } } class OfferingAsThoughEffect extends AsThoughEffectImpl { @@ -145,8 +182,8 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl { game.addEffect(effect, source); game.getState().setValue("offering_ok_" + card.getId(), true); game.getState().setValue("offering_Id_" + card.getId(), activationId); - game.informPlayers(player.getLogName() + " announces to offer " - + offer.getLogName() + " to cast " + game.informPlayers(player.getLogName() + " announces to offer " + + offer.getLogName() + " to cast " + GameLog.getColoredObjectName(spellToCast));// No id name to prevent to offer hand card knowledge after cancel casting return true; } @@ -192,7 +229,7 @@ class OfferingCostReductionEffect extends CostModificationEffectImpl { if (game.inCheckPlayableState()) { // Cost modifaction does not work correctly for checking available spells return false; } - if (abilityToModify.getSourceId().equals(source.getSourceId()) + if (abilityToModify.getSourceId().equals(source.getSourceId()) && abilityToModify instanceof SpellAbility) { Card card = game.getCard(source.getSourceId()); if (card != null) {