diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseAndDiscardCardsFromHandEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseAndDiscardCardsFromHandEffect.java index 2f3040d2a..58afd02e2 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseAndDiscardCardsFromHandEffect.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/ChooseAndDiscardCardsFromHandEffect.java @@ -7,6 +7,8 @@ import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.logic.actions.SubAction; import com.gempukku.lotro.logic.decisions.CardsSelectionDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.evaluator.ConstantEvaluator; +import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator; import com.gempukku.lotro.logic.timing.AbstractSubActionEffect; import com.gempukku.lotro.logic.timing.Action; import com.gempukku.lotro.logic.timing.Effect; @@ -18,11 +20,12 @@ public class ChooseAndDiscardCardsFromHandEffect extends AbstractSubActionEffect private Action _action; private String _playerId; private boolean _forced; - private int _minimum; - private int _maximum; + private Evaluator _minimum; + private Evaluator _maximum; private Filterable[] _filter; + private String _text = "Choose cards to discard"; - public ChooseAndDiscardCardsFromHandEffect(Action action, String playerId, boolean forced, int minimum, int maximum, Filterable... filters) { + public ChooseAndDiscardCardsFromHandEffect(Action action, String playerId, boolean forced, Evaluator minimum, Evaluator maximum, Filterable... filters) { _action = action; _playerId = playerId; _forced = forced; @@ -31,6 +34,10 @@ public class ChooseAndDiscardCardsFromHandEffect extends AbstractSubActionEffect _filter = filters; } + public ChooseAndDiscardCardsFromHandEffect(Action action, String playerId, boolean forced, int minimum, int maximum, Filterable... filters) { + this(action, playerId, forced, new ConstantEvaluator(minimum), new ConstantEvaluator(maximum), filters); + } + public ChooseAndDiscardCardsFromHandEffect(Action action, String playerId, boolean forced, int count, Filterable... filters) { this(action, playerId, forced, count, count, filters); } @@ -43,6 +50,10 @@ public class ChooseAndDiscardCardsFromHandEffect extends AbstractSubActionEffect this(action, playerId, forced, 1); } + public void setText(String text) { + _text = text; + } + @Override public Effect.Type getType() { return null; @@ -55,7 +66,8 @@ public class ChooseAndDiscardCardsFromHandEffect extends AbstractSubActionEffect @Override public boolean isPlayableInFull(LotroGame game) { - return Filters.filter(game.getGameState().getHand(_playerId), game.getGameState(), game.getModifiersQuerying(), _filter).size() >= _minimum; + return Filters.filter(game.getGameState().getHand(_playerId), game.getGameState(), game.getModifiersQuerying(), _filter).size() + >= _minimum.evaluateExpression(game.getGameState(), game.getModifiersQuerying(), null); } @Override @@ -64,16 +76,17 @@ public class ChooseAndDiscardCardsFromHandEffect extends AbstractSubActionEffect return; Collection hand = Filters.filter(game.getGameState().getHand(_playerId), game.getGameState(), game.getModifiersQuerying(), _filter); - int maximum = Math.min(_maximum, hand.size()); + int maximum = Math.min(_maximum.evaluateExpression(game.getGameState(), game.getModifiersQuerying(), null), hand.size()); - if (hand.size() <= _minimum) { + int minimum = _minimum.evaluateExpression(game.getGameState(), game.getModifiersQuerying(), null); + if (hand.size() <= minimum) { SubAction subAction = new SubAction(_action); subAction.appendEffect(new DiscardCardsFromHandEffect(_action.getActionSource(), _playerId, hand, _forced)); processSubAction(game, subAction); cardsBeingDiscardedCallback(hand); } else { game.getUserFeedback().sendAwaitingDecision(_playerId, - new CardsSelectionDecision(1, "Choose cards to discard", hand, _minimum, maximum) { + new CardsSelectionDecision(1, _text, hand, minimum, maximum) { @Override public void decisionMade(String result) throws DecisionResultInvalidException { Set cards = getSelectedCardsByResponse(result); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/MusterRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/MusterRule.java index 2b89f92dc..27ad08954 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/MusterRule.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/MusterRule.java @@ -5,15 +5,19 @@ import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.AbstractActionProxy; import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.GameState; import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.game.state.actions.DefaultActionsEnvironment; -import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.actions.OptionalTriggerAction; import com.gempukku.lotro.logic.effects.ChooseAndDiscardCardsFromHandEffect; import com.gempukku.lotro.logic.effects.DrawCardsEffect; +import com.gempukku.lotro.logic.modifiers.ModifiersQuerying; +import com.gempukku.lotro.logic.modifiers.evaluator.ConstantEvaluator; +import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator; import com.gempukku.lotro.logic.timing.EffectResult; -import java.util.LinkedList; +import java.util.Collection; +import java.util.Collections; import java.util.List; public class MusterRule { @@ -27,25 +31,33 @@ public class MusterRule { _actionsEnvironment.addAlwaysOnActionProxy( new AbstractActionProxy() { @Override - public List getOptionalAfterTriggers(String playerId, LotroGame game, EffectResult effectResult) { + public List getOptionalAfterTriggers(final String playerId, final LotroGame game, EffectResult effectResult) { if (effectResult.getType() == EffectResult.Type.START_OF_PHASE && game.getGameState().getCurrentPhase() == Phase.REGROUP && game.getGameState().getHand(playerId).size() > 0) { - List actions = new LinkedList(); - for (PhysicalCard musterCard : Filters.filterActive(game.getGameState(), game.getModifiersQuerying(), Keyword.MUSTER)) { - if (playerId.equals(musterCard.getOwner())) { - OptionalTriggerAction action = new OptionalTriggerAction("muster" + musterCard.getCardId(), musterCard); - action.setMessage(playerId + " uses Muster from " + GameUtils.getCardLink(musterCard)); - action.setText("Use Muster"); - action.appendCost( - new ChooseAndDiscardCardsFromHandEffect(action, playerId, false, 1)); - action.appendEffect( - new DrawCardsEffect(action, playerId, 1)); - actions.add(action); - } - } + PhysicalCard firstMuster = Filters.findFirstActive(game.getGameState(), game.getModifiersQuerying(), Filters.owner(playerId), Keyword.MUSTER); + if (firstMuster != null) { + final OptionalTriggerAction action = new OptionalTriggerAction("muster", firstMuster); + action.setText("Use Muster"); + ChooseAndDiscardCardsFromHandEffect effect = new ChooseAndDiscardCardsFromHandEffect(action, playerId, false, + new ConstantEvaluator(0), new Evaluator() { + @Override + public int evaluateExpression(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard cardAffected) { + return Filters.filterActive(gameState, modifiersQuerying, Filters.owner(playerId), Keyword.MUSTER).size(); + } + }) { + @Override + protected void cardsBeingDiscardedCallback(Collection cardsBeingDiscarded) { + if (cardsBeingDiscarded.size() > 0) + action.appendEffect( + new DrawCardsEffect(action, playerId, cardsBeingDiscarded.size())); + } + }; + effect.setText("Choose cards to discard to Muster"); + action.appendEffect(effect); - return actions; + return Collections.singletonList(action); + } } return null; } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java index 6fd82bb6e..6303333c9 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/IndividualCardAtTest.java @@ -227,8 +227,10 @@ public class IndividualCardAtTest extends AbstractAtTest { skipMulligans(); PhysicalCardImpl mumakChieftain = new PhysicalCardImpl(100, "10_45", P1, _library.getLotroCardBlueprint("10_45")); + PhysicalCardImpl mumakChieftain2 = new PhysicalCardImpl(101, "10_45", P1, _library.getLotroCardBlueprint("10_45")); _game.getGameState().addCardToZone(_game, mumakChieftain, Zone.HAND); + _game.getGameState().addCardToZone(_game, mumakChieftain2, Zone.DECK); // End fellowship phase playerDecided(P1, ""); @@ -241,9 +243,20 @@ public class IndividualCardAtTest extends AbstractAtTest { assertEquals(1, _game.getGameState().getWounds(_game.getGameState().getRingBearer(P1))); assertEquals(1, _game.getGameState().getHand(P1).size()); + final AwaitingDecision musterUseDecision = _userFeedback.getAwaitingDecision(P1); + assertEquals(AwaitingDecisionType.CARD_ACTION_CHOICE, musterUseDecision.getDecisionType()); + validateContents(new String[]{"" + _game.getGameState().getRingBearer(P1).getCardId()}, ((String[]) musterUseDecision.getDecisionParameters().get("cardId"))); playerDecided(P1, "0"); - assertEquals(0, _game.getGameState().getHand(P1).size()); + final AwaitingDecision musterDiscardDecision = _userFeedback.getAwaitingDecision(P1); + assertEquals(AwaitingDecisionType.CARD_SELECTION, musterDiscardDecision.getDecisionType()); + validateContents(new String[]{"" + mumakChieftain.getCardId()}, ((String[]) musterDiscardDecision.getDecisionParameters().get("cardId"))); + playerDecided(P1, ((String[]) musterDiscardDecision.getDecisionParameters().get("cardId"))[0]); + + assertEquals(1, _game.getGameState().getHand(P1).size()); + + assertEquals(Zone.HAND, mumakChieftain2.getZone()); + assertEquals(Phase.REGROUP, _game.getGameState().getCurrentPhase()); } @Test diff --git a/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html b/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html index 25dc93695..e714297b4 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html +++ b/gemp-lotr/gemp-lotr-web/src/main/webapp/includes/changeLog.html @@ -1,6 +1,10 @@
 23 Oct. 2012
 - "Harrowdale" might be working fine this time around.
+- Changed how Muster works now. At the start of the regroup phase, one of your muster cards will light up (unfortunately
+all optional effects have to be used via cards). If you want to use Muster, just click the card (right-click to be sure
+what effect you're using). Then you choose which cards you want to discard, up to the number of Muster cards you have.
+All cards are discarded and then you draw an equal number of cards.
 
 16 Oct. 2012
 - "Down to the Last Child" now triggers on companion/ally losing skirmish, not Uruk-hai winning, so if companion loses