diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractPermanent.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractPermanent.java index 45dfb16c5..74639e2af 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractPermanent.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/AbstractPermanent.java @@ -31,7 +31,7 @@ public class AbstractPermanent extends AbstractLotroCardBlueprint { @Override public PlayPermanentAction getPlayCardAction(String playerId, LotroGame game, PhysicalCard self, int twilightModifier, boolean ignoreRoamingPenalty) { - PlayPermanentAction action = new PlayPermanentAction(self, _playedToZone, twilightModifier); + PlayPermanentAction action = new PlayPermanentAction(self, _playedToZone, twilightModifier, ignoreRoamingPenalty); DiscountEffect discountEffect = getDiscountEffect(action, playerId, game, self); if (discountEffect != null) action.setDiscountEffect(discountEffect); @@ -55,7 +55,7 @@ public class AbstractPermanent extends AbstractLotroCardBlueprint { } protected int getPotentialExtraPaymentDiscount(String playerId, LotroGame game, PhysicalCard self) { - // Always non-negative + // Always non-negative return 0; } diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/AttachPermanentAction.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/AttachPermanentAction.java index 1a40cb68c..b16e65a88 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/AttachPermanentAction.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/AttachPermanentAction.java @@ -1,8 +1,12 @@ package com.gempukku.lotro.cards.actions; +import com.gempukku.lotro.cards.effects.DiscountEffect; import com.gempukku.lotro.cards.effects.ExertCharactersEffect; import com.gempukku.lotro.cards.effects.PayPlayOnTwilightCostEffect; import com.gempukku.lotro.cards.effects.ShuffleDeckEffect; +import com.gempukku.lotro.cards.effects.discount.ToilDiscountEffect; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Side; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.filters.Filter; import com.gempukku.lotro.game.PhysicalCard; @@ -16,7 +20,7 @@ import com.gempukku.lotro.logic.timing.Effect; import java.util.*; -public class AttachPermanentAction extends AbstractCostToEffectAction { +public class AttachPermanentAction extends AbstractCostToEffectAction implements DiscountableAction { private PhysicalCard _cardToAttach; private boolean _cardRemoved; @@ -35,6 +39,13 @@ public class AttachPermanentAction extends AbstractCostToEffectAction { private PhysicalCard _target; + private boolean _discountResolved; + private DiscountEffect _discountEffect; + + private boolean _discountApplied; + + private int _twilightModifier; + public AttachPermanentAction(final LotroGame game, final PhysicalCard card, Filter filter, final Map attachCostModifiers, final int twilightModifier) { _cardToAttach = card; @@ -55,11 +66,12 @@ public class AttachPermanentAction extends AbstractCostToEffectAction { if (filterIntegerEntry.getKey().accepts(game.getGameState(), game.getModifiersQuerying(), target)) modifier += filterIntegerEntry.getValue(); + _twilightModifier = modifier; + List preCostEffects = new LinkedList(); preCostEffects.add(new SendMessageEffect(card.getOwner() + " plays " + GameUtils.getCardLink(card) + " from " + zone.getHumanReadable() + " on " + GameUtils.getCardLink(target))); if (zone == Zone.DECK) preCostEffects.add(new ShuffleDeckEffect(card.getOwner())); - appendCost(new PayPlayOnTwilightCostEffect(card, target, modifier)); _preCostIterator = preCostEffects.iterator(); @@ -73,6 +85,11 @@ public class AttachPermanentAction extends AbstractCostToEffectAction { return Type.PLAY_CARD; } + @Override + public void setDiscountEffect(DiscountEffect discountEffect) { + _discountEffect = discountEffect; + } + public PhysicalCard getTarget() { return _target; } @@ -98,6 +115,9 @@ public class AttachPermanentAction extends AbstractCostToEffectAction { @Override public Effect nextEffect(LotroGame game) { + if (_preCostIterator.hasNext()) + return _preCostIterator.next(); + if (!_cardRemoved) { _cardRemoved = true; game.getGameState().removeCardsFromZone(_cardToAttach.getOwner(), Collections.singleton(_cardToAttach)); @@ -108,10 +128,35 @@ public class AttachPermanentAction extends AbstractCostToEffectAction { return _chooseTargetEffect; } - if (_playCardEffect != null) { - if (_preCostIterator.hasNext()) - return _preCostIterator.next(); + if (!_discountResolved) { + _discountResolved = true; + if (_discountEffect == null) { + int toilCount = game.getModifiersQuerying().getKeywordCount(game.getGameState(), _cardToAttach, Keyword.TOIL); + if (toilCount > 0) { + _discountEffect = new ToilDiscountEffect(this, _cardToAttach, _cardToAttach.getOwner(), _cardToAttach.getBlueprint().getCulture(), toilCount); + } + } + if (_discountEffect != null) { + int requiredDiscount = 0; + if (_cardToAttach.getBlueprint().getSide() == Side.SHADOW) { + int twilightCost = game.getModifiersQuerying().getPlayOnTwilightCost(game.getGameState(), _cardToAttach, _target); + int underPool = twilightCost - game.getGameState().getTwilightPool(); + if (underPool > 0) + requiredDiscount = underPool; + } + _discountEffect.setMinimalRequiredDiscount(requiredDiscount); + return _discountEffect; + } + } + if (!_discountApplied) { + _discountApplied = true; + if (_discountEffect != null) + _twilightModifier -= _discountEffect.getDiscountPaidFor(); + insertCost(new PayPlayOnTwilightCostEffect(_cardToAttach, _target, _twilightModifier)); + } + + if (_playCardEffect != null) { if (!isCostFailed()) { Effect cost = getNextCost(); if (cost != null) diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/DiscountableAction.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/DiscountableAction.java new file mode 100644 index 000000000..565cbf240 --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/DiscountableAction.java @@ -0,0 +1,7 @@ +package com.gempukku.lotro.cards.actions; + +import com.gempukku.lotro.cards.effects.DiscountEffect; + +public interface DiscountableAction { + public void setDiscountEffect(DiscountEffect discountEffect); +} diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayEventAction.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayEventAction.java index 619cc8f1c..f253d8aa4 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayEventAction.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayEventAction.java @@ -1,7 +1,11 @@ package com.gempukku.lotro.cards.actions; +import com.gempukku.lotro.cards.effects.DiscountEffect; import com.gempukku.lotro.cards.effects.PayTwilightCostEffect; import com.gempukku.lotro.cards.effects.ShuffleDeckEffect; +import com.gempukku.lotro.cards.effects.discount.ToilDiscountEffect; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Side; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.LotroGame; @@ -15,7 +19,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -public class PlayEventAction extends AbstractCostToEffectAction { +public class PlayEventAction extends AbstractCostToEffectAction implements DiscountableAction { private PhysicalCard _eventPlayed; private boolean _requiresRanger; @@ -31,6 +35,10 @@ public class PlayEventAction extends AbstractCostToEffectAction { private boolean _skipDiscardCard; private String _text; + private boolean _discountResolved; + private DiscountEffect _discountEffect; + + private boolean _discountApplied; public PlayEventAction(PhysicalCard card) { this(card, false); @@ -41,7 +49,6 @@ public class PlayEventAction extends AbstractCostToEffectAction { _requiresRanger = requiresRanger; List preCostEffects = new LinkedList(); - appendCost(new PayTwilightCostEffect(card)); if (card.getZone() == Zone.DECK) preCostEffects.add(new ShuffleDeckEffect(card.getOwner())); @@ -61,6 +68,11 @@ public class PlayEventAction extends AbstractCostToEffectAction { return Type.PLAY_CARD; } + @Override + public void setDiscountEffect(DiscountEffect discountEffect) { + _discountEffect = discountEffect; + } + public boolean isRequiresRanger() { return _requiresRanger; } @@ -90,6 +102,9 @@ public class PlayEventAction extends AbstractCostToEffectAction { @Override public Effect nextEffect(LotroGame game) { + if (_preCostIterator.hasNext()) + return _preCostIterator.next(); + if (!_cardRemoved) { _cardRemoved = true; game.getGameState().sendMessage(_eventPlayed.getOwner() + " plays " + GameUtils.getCardLink(_eventPlayed) + " from " + _eventPlayed.getZone().getHumanReadable()); @@ -100,8 +115,34 @@ public class PlayEventAction extends AbstractCostToEffectAction { game.getGameState().eventPlayed(_eventPlayed); } - if (_preCostIterator.hasNext()) - return _preCostIterator.next(); + if (!_discountResolved) { + _discountResolved = true; + if (_discountEffect == null) { + int toilCount = game.getModifiersQuerying().getKeywordCount(game.getGameState(), _eventPlayed, Keyword.TOIL); + if (toilCount > 0) { + _discountEffect = new ToilDiscountEffect(this, _eventPlayed, _eventPlayed.getOwner(), _eventPlayed.getBlueprint().getCulture(), toilCount); + } + } + if (_discountEffect != null) { + int requiredDiscount = 0; + if (_eventPlayed.getBlueprint().getSide() == Side.SHADOW) { + int twilightCost = game.getModifiersQuerying().getTwilightCost(game.getGameState(), _eventPlayed, false); + int underPool = twilightCost - game.getGameState().getTwilightPool(); + if (underPool > 0) + requiredDiscount = underPool; + } + _discountEffect.setMinimalRequiredDiscount(requiredDiscount); + return _discountEffect; + } + } + + if (!_discountApplied) { + _discountApplied = true; + int twilightModifier = 0; + if (_discountEffect != null) + twilightModifier -= _discountEffect.getDiscountPaidFor(); + insertCost(new PayTwilightCostEffect(_eventPlayed, twilightModifier)); + } if (!isCostFailed()) { Effect cost = getNextCost(); diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayPermanentAction.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayPermanentAction.java index 96c992835..672ace660 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayPermanentAction.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/actions/PlayPermanentAction.java @@ -3,6 +3,9 @@ package com.gempukku.lotro.cards.actions; import com.gempukku.lotro.cards.effects.DiscountEffect; import com.gempukku.lotro.cards.effects.PayTwilightCostEffect; import com.gempukku.lotro.cards.effects.ShuffleDeckEffect; +import com.gempukku.lotro.cards.effects.discount.ToilDiscountEffect; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Side; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.LotroGame; @@ -17,10 +20,11 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -public class PlayPermanentAction extends AbstractCostToEffectAction { +public class PlayPermanentAction extends AbstractCostToEffectAction implements DiscountableAction { private PhysicalCard _permanentPlayed; private Zone _zone; private int _twilightModifier; + private boolean _ignoreRoamingPenalty; private boolean _cardRemoved; @@ -36,10 +40,11 @@ public class PlayPermanentAction extends AbstractCostToEffectAction { private boolean _discountApplied; - public PlayPermanentAction(PhysicalCard card, Zone zone, int twilightModifier) { + public PlayPermanentAction(PhysicalCard card, Zone zone, int twilightModifier, boolean ignoreRoamingPenalty) { _permanentPlayed = card; _zone = zone; _twilightModifier = twilightModifier; + _ignoreRoamingPenalty = ignoreRoamingPenalty; List preCostEffects = new LinkedList(); preCostEffects.add(new SendMessageEffect(card.getOwner() + " plays " + GameUtils.getCardLink(card) + " from " + card.getZone().getHumanReadable())); @@ -63,6 +68,7 @@ public class PlayPermanentAction extends AbstractCostToEffectAction { return Type.PLAY_CARD; } + @Override public void setDiscountEffect(DiscountEffect discountEffect) { _discountEffect = discountEffect; } @@ -97,15 +103,30 @@ public class PlayPermanentAction extends AbstractCostToEffectAction { if (!_discountResolved) { _discountResolved = true; - if (_discountEffect != null) + if (_discountEffect == null) { + int toilCount = game.getModifiersQuerying().getKeywordCount(game.getGameState(), _permanentPlayed, Keyword.TOIL); + if (toilCount > 0) { + _discountEffect = new ToilDiscountEffect(this, _permanentPlayed, _permanentPlayed.getOwner(), _permanentPlayed.getBlueprint().getCulture(), toilCount); + } + } + if (_discountEffect != null) { + int requiredDiscount = 0; + if (_permanentPlayed.getBlueprint().getSide() == Side.SHADOW) { + int twilightCost = game.getModifiersQuerying().getTwilightCost(game.getGameState(), _permanentPlayed, _ignoreRoamingPenalty); + int underPool = twilightCost - game.getGameState().getTwilightPool(); + if (underPool > 0) + requiredDiscount = underPool; + } + _discountEffect.setMinimalRequiredDiscount(requiredDiscount); return _discountEffect; + } } if (!_discountApplied) { _discountApplied = true; if (_discountEffect != null) _twilightModifier -= _discountEffect.getDiscountPaidFor(); - insertCost(new PayTwilightCostEffect(_permanentPlayed, _twilightModifier)); + insertCost(new PayTwilightCostEffect(_permanentPlayed, _twilightModifier, _ignoreRoamingPenalty)); } if (!isCostFailed()) { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/PayTwilightCostEffect.java b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/PayTwilightCostEffect.java index 608ea634c..e835abb4e 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/PayTwilightCostEffect.java +++ b/gemp-lotr/gemp-lotr-cards/src/main/java/com/gempukku/lotro/cards/effects/PayTwilightCostEffect.java @@ -8,14 +8,20 @@ import com.gempukku.lotro.logic.timing.Effect; public class PayTwilightCostEffect extends AbstractEffect { private PhysicalCard _physicalCard; private int _twilightModifier; + private boolean _ignoreRoamingPenalty; public PayTwilightCostEffect(PhysicalCard physicalCard) { this(physicalCard, 0); } public PayTwilightCostEffect(PhysicalCard physicalCard, int twilightModifier) { + this(physicalCard, twilightModifier, false); + } + + public PayTwilightCostEffect(PhysicalCard physicalCard, int twilightModifier, boolean ignoreRoamingPenalty) { _physicalCard = physicalCard; _twilightModifier = twilightModifier; + _ignoreRoamingPenalty = ignoreRoamingPenalty; } @Override @@ -30,7 +36,7 @@ public class PayTwilightCostEffect extends AbstractEffect { @Override public boolean isPlayableInFull(LotroGame game) { - int twilightCost = _twilightModifier + game.getModifiersQuerying().getTwilightCost(game.getGameState(), _physicalCard, false); + int twilightCost = _twilightModifier + game.getModifiersQuerying().getTwilightCost(game.getGameState(), _physicalCard, _ignoreRoamingPenalty); String currentPlayerId = game.getGameState().getCurrentPlayerId(); if (!currentPlayerId.equals(_physicalCard.getOwner())) { @@ -43,7 +49,7 @@ public class PayTwilightCostEffect extends AbstractEffect { @Override protected FullEffectResult playEffectReturningResult(LotroGame game) { - int twilightCost = _twilightModifier + game.getModifiersQuerying().getTwilightCost(game.getGameState(), _physicalCard, false); + int twilightCost = _twilightModifier + game.getModifiersQuerying().getTwilightCost(game.getGameState(), _physicalCard, _ignoreRoamingPenalty); String currentPlayerId = game.getGameState().getCurrentPlayerId(); if (currentPlayerId.equals(_physicalCard.getOwner())) {