"Treebeard"
And Unhasty keyword.
This commit is contained in:
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
|
||||
public class AbstractAlly extends AbstractPermanent {
|
||||
private Block _siteBlock;
|
||||
private int _siteNumber;
|
||||
private int[] _siteNumbers;
|
||||
private int _strength;
|
||||
private int _vitality;
|
||||
private Race _race;
|
||||
@@ -24,9 +24,17 @@ public class AbstractAlly extends AbstractPermanent {
|
||||
}
|
||||
|
||||
public AbstractAlly(int twilight, Block siteBlock, int siteNumber, int strength, int vitality, Race race, Culture culture, String name, boolean unique) {
|
||||
this(twilight, siteBlock, new int[]{siteNumber}, strength, vitality, race, culture, name, unique);
|
||||
}
|
||||
|
||||
public AbstractAlly(int twilight, Block siteBlock, int[] siteNumbers, int strength, int vitality, Race race, Culture culture, String name) {
|
||||
this(twilight, siteBlock, siteNumbers, strength, vitality, race, culture, name, false);
|
||||
}
|
||||
|
||||
public AbstractAlly(int twilight, Block siteBlock, int[] siteNumbers, int strength, int vitality, Race race, Culture culture, String name, boolean unique) {
|
||||
super(Side.FREE_PEOPLE, twilight, CardType.ALLY, culture, Zone.SUPPORT, name, unique);
|
||||
_siteBlock = siteBlock;
|
||||
_siteNumber = siteNumber;
|
||||
_siteNumbers = siteNumbers;
|
||||
_strength = strength;
|
||||
_vitality = vitality;
|
||||
_race = race;
|
||||
@@ -55,13 +63,13 @@ public class AbstractAlly extends AbstractPermanent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getSiteBlock() {
|
||||
return _siteBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getSiteNumber() {
|
||||
return _siteNumber;
|
||||
public final boolean isAllyAtHome(int siteNumber, Block block) {
|
||||
if (block != _siteBlock)
|
||||
return false;
|
||||
for (int number : _siteNumbers)
|
||||
if (number == siteNumber)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,16 +48,15 @@ public abstract class AbstractAttachableFPPossession extends AbstractAttachable
|
||||
validTransferFilter = Filters.and(validTargetFilter,
|
||||
Filters.or(
|
||||
Filters.type(CardType.COMPANION),
|
||||
Filters.allyOnHomeSite()));
|
||||
} else if (attachedTo.getSiteNumber() == gameState.getCurrentSiteNumber()
|
||||
&& attachedTo.getSiteBlock() == gameState.getCurrentSite().getBlueprint().getSiteBlock()) {
|
||||
Filters.isAllyAtHome()));
|
||||
} else if (attachedTo.isAllyAtHome(gameState.getCurrentSiteNumber(), gameState.getCurrentSite().getBlueprint().getSiteBlock())) {
|
||||
validTransferFilter = Filters.and(validTargetFilter,
|
||||
Filters.or(
|
||||
Filters.type(CardType.COMPANION),
|
||||
Filters.allyOnHomeSite()));
|
||||
Filters.isAllyAtHome()));
|
||||
} else {
|
||||
validTransferFilter = Filters.and(validTargetFilter,
|
||||
Filters.type(CardType.ALLY), Filters.siteNumber(attachedTo.getSiteNumber()), Filters.siteBlock(attachedTo.getSiteBlock())
|
||||
Filters.type(CardType.ALLY), Filters.isAllyAtHome()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +115,11 @@ public abstract class AbstractLotroCardBlueprint implements LotroCardBlueprint {
|
||||
throw new UnsupportedOperationException("This method should not be called on this card");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllyAtHome(int siteNumber, Block siteBlock) {
|
||||
throw new UnsupportedOperationException("This method should not be called on this card");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getSiteBlock() {
|
||||
throw new UnsupportedOperationException("This method should not be called on this card");
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.gempukku.lotro.cards.modifiers;
|
||||
|
||||
import com.gempukku.lotro.common.Culture;
|
||||
import com.gempukku.lotro.common.Keyword;
|
||||
import com.gempukku.lotro.common.Side;
|
||||
import com.gempukku.lotro.filters.Filter;
|
||||
import com.gempukku.lotro.game.PhysicalCard;
|
||||
import com.gempukku.lotro.game.state.GameState;
|
||||
@@ -8,8 +11,11 @@ import com.gempukku.lotro.logic.modifiers.ModifierEffect;
|
||||
import com.gempukku.lotro.logic.modifiers.ModifiersQuerying;
|
||||
|
||||
public class AllyParticipatesInArcheryFireAndSkirmishesModifier extends AbstractModifier {
|
||||
private PhysicalCard _source;
|
||||
|
||||
public AllyParticipatesInArcheryFireAndSkirmishesModifier(PhysicalCard source, Filter affectFilter) {
|
||||
super(source, "Can participate in archery and skirmishes", affectFilter, new ModifierEffect[]{ModifierEffect.PRESENCE_MODIFIER});
|
||||
_source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -18,7 +24,9 @@ public class AllyParticipatesInArcheryFireAndSkirmishesModifier extends Abstract
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
|
||||
return true;
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
|
||||
boolean unhasty = modifiersQuerying.hasKeyword(gameState, card, Keyword.UNHASTY);
|
||||
return sidePlayer == Side.SHADOW
|
||||
|| !unhasty || _source.getBlueprint().getCulture() == Culture.GANDALF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,11 @@ public class SimpleLotroCardBlueprint implements LotroCardBlueprint {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllyAtHome(int siteNumber, Block siteBlock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Action> getOptionalAfterActions(String playerId, LotroGame game, EffectResult effectResult, PhysicalCard self) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.gempukku.lotro.cards.set4.gandalf;
|
||||
|
||||
import com.gempukku.lotro.cards.AbstractAlly;
|
||||
import com.gempukku.lotro.cards.PlayConditions;
|
||||
import com.gempukku.lotro.cards.effects.AddTwilightEffect;
|
||||
import com.gempukku.lotro.cards.effects.ChooseArbitraryCardsEffect;
|
||||
import com.gempukku.lotro.cards.effects.ExertCharactersEffect;
|
||||
import com.gempukku.lotro.cards.effects.StackCardFromPlayEffect;
|
||||
import com.gempukku.lotro.common.*;
|
||||
import com.gempukku.lotro.filters.Filters;
|
||||
import com.gempukku.lotro.game.PhysicalCard;
|
||||
import com.gempukku.lotro.game.state.LotroGame;
|
||||
import com.gempukku.lotro.logic.actions.ActivateCardAction;
|
||||
import com.gempukku.lotro.logic.effects.ChooseActiveCardEffect;
|
||||
import com.gempukku.lotro.logic.effects.DiscardCardsFromPlayEffect;
|
||||
import com.gempukku.lotro.logic.timing.Action;
|
||||
import com.gempukku.lotro.logic.timing.Effect;
|
||||
import com.gempukku.lotro.logic.timing.EffectResult;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Set: The Two Towers
|
||||
* Side: Free
|
||||
* Culture: Gandalf
|
||||
* Twilight Cost: 4
|
||||
* Type: Ally • Home 2T & 8T • Ent
|
||||
* Strength: 12
|
||||
* Vitality: 4
|
||||
* Site: 2T, 8T
|
||||
* Game Text: Unhasty. Response: If an unbound Hobbit is about to be discarded, stack him here instead.
|
||||
* Fellowship: Exert Treebeard and add(1) to play an unbound Hobbit stacked here.
|
||||
*/
|
||||
public class Card4_103 extends AbstractAlly {
|
||||
public Card4_103() {
|
||||
super(4, Block.TWO_TOWERS, new int[]{2, 8}, 12, 4, Race.ENT, Culture.GANDALF, "Treebeard", true);
|
||||
addKeyword(Keyword.UNHASTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Action> getOptionalBeforeActions(String playerId, LotroGame game, Effect effect, final PhysicalCard self) {
|
||||
if (effect.getType() == EffectResult.Type.DISCARD_FROM_PLAY
|
||||
&& PlayConditions.canUseFPCardDuringPhase(game.getGameState(), null, self)) {
|
||||
DiscardCardsFromPlayEffect discardEffect = (DiscardCardsFromPlayEffect) effect;
|
||||
Collection<PhysicalCard> discardedHobbits = Filters.filter(discardEffect.getAffectedCardsMinusPrevented(game), game.getGameState(), game.getModifiersQuerying(), Filters.unboundCompanion(), Filters.race(Race.HOBBIT));
|
||||
if (discardedHobbits.size() > 0) {
|
||||
final ActivateCardAction action = new ActivateCardAction(self, Keyword.RESPONSE);
|
||||
action.appendEffect(
|
||||
new ChooseActiveCardEffect(self, playerId, "Choose unbound hobbit", Filters.in(discardedHobbits)) {
|
||||
@Override
|
||||
protected void cardSelected(PhysicalCard card) {
|
||||
action.insertEffect(
|
||||
new StackCardFromPlayEffect(card, self));
|
||||
}
|
||||
});
|
||||
return Collections.singletonList(action);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends Action> getExtraInPlayPhaseActions(final String playerId, LotroGame game, PhysicalCard self) {
|
||||
if (PlayConditions.canUseFPCardDuringPhase(game.getGameState(), Phase.FELLOWSHIP, self)
|
||||
&& PlayConditions.canExert(self, game.getGameState(), game.getModifiersQuerying(), self)
|
||||
&& Filters.filter(game.getGameState().getStackedCards(self), game.getGameState(), game.getModifiersQuerying(), Filters.unboundCompanion(), Filters.race(Race.HOBBIT), Filters.playable(game)).size() > 0) {
|
||||
ActivateCardAction action = new ActivateCardAction(self, Keyword.FELLOWSHIP);
|
||||
action.appendCost(
|
||||
new ExertCharactersEffect(self, self));
|
||||
action.appendCost(
|
||||
new AddTwilightEffect(self, 1));
|
||||
action.appendEffect(
|
||||
new ChooseArbitraryCardsEffect(playerId, "Choose an Orc to play", game.getGameState().getStackedCards(self), Filters.playable(game), 1, 1) {
|
||||
@Override
|
||||
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> stackedHobbits) {
|
||||
if (stackedHobbits.size() > 0) {
|
||||
PhysicalCard stackedHobbit = stackedHobbits.iterator().next();
|
||||
game.getActionsEnvironment().addActionToStack(stackedHobbit.getBlueprint().getPlayCardAction(playerId, game, stackedHobbit, 0));
|
||||
}
|
||||
}
|
||||
});
|
||||
return Collections.singletonList(action);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ public enum Keyword {
|
||||
RIVER("River", true), PLAINS("Plains", true), UNDERGROUND("Underground", true), SANCTUARY("Sanctuary", true), FOREST("Forest", true), MARSH("Marsh", true), MOUNTAIN("Mountain", true),
|
||||
BATTLEGROUND("Battleground", true),
|
||||
|
||||
DAMAGE("Damage", true, true), DEFENDER("Defender", true, true), FIERCE("Fierce", true), ARCHER("Archer", true), RANGER("Ranger", true), TRACKER("Tracker", true),
|
||||
DAMAGE("Damage", true, true), DEFENDER("Defender", true, true), FIERCE("Fierce", true), ARCHER("Archer", true), UNHASTY("Unhasty", true),
|
||||
RANGER("Ranger", true), TRACKER("Tracker", true),
|
||||
|
||||
HAND_WEAPON("Hand Weapon"), ARMOR("Armor"), HELM("Helm"), MOUNT("Mount"), RANGED_WEAPON("Ranged Weapon"),
|
||||
CLOAK("Cloak"), PIPE("Pipe"), PIPEWEED("Pipeweed"), SHIELD("Shield"), BRACERS("Bracers"), STAFF("Staff"), RING("Ring"),
|
||||
|
||||
@@ -82,19 +82,6 @@ public class Filters {
|
||||
};
|
||||
}
|
||||
|
||||
public static Filter allyOnHomeSite() {
|
||||
return Filters.and(
|
||||
Filters.type(CardType.ALLY),
|
||||
new Filter() {
|
||||
@Override
|
||||
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
|
||||
return physicalCard.getBlueprint().getSiteNumber() == gameState.getCurrentSiteNumber()
|
||||
&& physicalCard.getBlueprint().getSiteBlock() == gameState.getCurrentSite().getBlueprint().getSiteBlock();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static Filter siteBlock(final Block block) {
|
||||
return new Filter() {
|
||||
@Override
|
||||
@@ -259,6 +246,17 @@ public class Filters {
|
||||
};
|
||||
}
|
||||
|
||||
public static Filter isAllyAtHome() {
|
||||
return Filters.and(
|
||||
Filters.type(CardType.ALLY),
|
||||
new Filter() {
|
||||
@Override
|
||||
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
|
||||
return physicalCard.getBlueprint().isAllyAtHome(gameState.getCurrentSiteNumber(), gameState.getCurrentSiteBlock());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Filter siteNumber(final int siteNumber) {
|
||||
return new Filter() {
|
||||
@Override
|
||||
|
||||
@@ -38,6 +38,8 @@ public interface LotroCardBlueprint {
|
||||
|
||||
public int getResistance();
|
||||
|
||||
public boolean isAllyAtHome(int siteNumber, Block siteBlock);
|
||||
|
||||
public List<? extends Modifier> getAlwaysOnModifiers(PhysicalCard self);
|
||||
|
||||
public boolean checkPlayRequirements(String playerId, LotroGame game, PhysicalCard self, int twilightModifier);
|
||||
|
||||
@@ -121,7 +121,7 @@ public abstract class AbstractModifier implements Modifier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, ModifiersQuerying modifiersQuerying, PhysicalCard card) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public interface Modifier {
|
||||
|
||||
public boolean isAllyParticipateInArcheryFire(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card);
|
||||
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard card);
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, ModifiersQuerying modifiersQuerying, PhysicalCard card);
|
||||
|
||||
public int getArcheryTotal(GameState gameState, ModifiersQuerying modifiersQuerying, Side side, int result);
|
||||
|
||||
|
||||
@@ -328,10 +328,10 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, PhysicalCard card) {
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, PhysicalCard card) {
|
||||
for (Modifier modifier : getModifiers(ModifierEffect.PRESENCE_MODIFIER)) {
|
||||
if (affectsCardWithSkipSet(gameState, card, modifier))
|
||||
if (modifier.isAllyParticipateInSkirmishes(gameState, this, card))
|
||||
if (modifier.isAllyParticipateInSkirmishes(gameState, sidePlayer, this, card))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -54,7 +54,7 @@ public interface ModifiersQuerying {
|
||||
// Assignments
|
||||
public boolean canBeAssignedToSkirmish(GameState gameState, Side playerSide, PhysicalCard card);
|
||||
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, PhysicalCard card);
|
||||
public boolean isAllyParticipateInSkirmishes(GameState gameState, Side sidePlayer, PhysicalCard card);
|
||||
|
||||
public boolean isAllyParticipateInArcheryFire(GameState gameState, PhysicalCard card);
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public class FreePeoplePlayerAssignsMinionsGameProcess implements GameProcess {
|
||||
new Filter() {
|
||||
@Override
|
||||
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
|
||||
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, physicalCard);
|
||||
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, Side.FREE_PEOPLE, physicalCard);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ShadowPlayerAssignsHisMinionsGameProcess implements GameProcess {
|
||||
new Filter() {
|
||||
@Override
|
||||
public boolean accepts(GameState gameState, ModifiersQuerying modifiersQuerying, PhysicalCard physicalCard) {
|
||||
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, physicalCard);
|
||||
return modifiersQuerying.isAllyParticipateInSkirmishes(gameState, Side.SHADOW, physicalCard);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user