* Fixed wrong timer handling while other player controlled a player's turn. Attackers now marked with blue frame. Playable cards have a violet frame. If a player has to select cards from hand, the possible cards are marked yellow now. Discard of multiple cards now marks already selected cards and happens in one selection.

This commit is contained in:
LevelX2 2014-11-26 01:48:00 +01:00
parent 194efe6237
commit 67479bb5a4
20 changed files with 205 additions and 163 deletions

View file

@ -31,13 +31,10 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
@ -48,7 +45,6 @@ public class DiscardTargetEffect extends OneShotEffect {
protected DynamicValue amount;
protected boolean randomDiscard;
protected boolean setTargetPointer;
public DiscardTargetEffect(DynamicValue amount) {
this(amount, false);
@ -64,22 +60,22 @@ public class DiscardTargetEffect extends OneShotEffect {
this(new StaticValue(amount));
}
/**
*
* @param amount amount of cards to discard
* @param randomDiscard discard the cards by random
*
*/
public DiscardTargetEffect(int amount, boolean randomDiscard) {
this(new StaticValue(amount), randomDiscard);
}
public DiscardTargetEffect(int amount, boolean randomDiscard, boolean setTargetPointer) {
super(Outcome.Discard);
this.randomDiscard = randomDiscard;
this.amount = new StaticValue(amount);
this.setTargetPointer = setTargetPointer;
}
public DiscardTargetEffect(final DiscardTargetEffect effect) {
super(effect);
this.amount = effect.amount.copy();
this.randomDiscard = effect.randomDiscard;
this.setTargetPointer = effect.setTargetPointer;
}
@Override
@ -91,23 +87,7 @@ public class DiscardTargetEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
if (randomDiscard) {
int maxAmount = Math.min(amount.calculate(game, source, this), player.getHand().size());
for (int i = 0; i < maxAmount; i++) {
Card card = player.getHand().getRandom(game);
if (card != null) {
player.discard(card, source, game);
if (setTargetPointer) {
for (Effect effect : source.getEffects()) {
effect.setTargetPointer(new FixedTarget(card.getId()));
}
}
}
}
} else {
player.discard(amount.calculate(game, source, this), source, game);
}
player.discard(amount.calculate(game, source, this), randomDiscard, source, game);
return true;
}
return false;

View file

@ -988,7 +988,7 @@ public abstract class GameImpl implements Game, Serializable {
int deduction = 1;
if (freeMulligans > 0) {
if (usedFreeMulligans != null && usedFreeMulligans.containsKey(player.getId())) {
int used = usedFreeMulligans.get(player.getId()).intValue();
int used = usedFreeMulligans.get(player.getId());
if (used < freeMulligans ) {
deduction = 0;
}

View file

@ -122,6 +122,7 @@ import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetDiscard;
import mage.util.CardUtil;
import mage.watchers.common.BloodthirstWatcher;
import org.apache.log4j.Logger;
@ -563,6 +564,9 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public void setGameUnderYourControl(boolean value) {
this.isGameUnderControl = value;
if (isGameUnderControl) {
this.turnController = getId();
}
}
@Override
@ -623,12 +627,7 @@ public abstract class PlayerImpl implements Player, Serializable {
public void discardToMax(Game game) {
if (hand.size() > this.maxHandSize) {
game.informPlayers(new StringBuilder(getName()).append(" discards down to ").append(this.maxHandSize).append(this.maxHandSize == 1?" hand card":" hand cards").toString());
while (isInGame() && hand.size() > this.maxHandSize) {
TargetDiscard target = new TargetDiscard(playerId);
target.setTargetName(new StringBuilder(" card to discard (").append(hand.size() - this.maxHandSize).append(" in total)").toString());
choose(Outcome.Discard, target, null, game);
discard(hand.get(target.getFirstTarget(), game), null, game);
}
discard(hand.size() - this.maxHandSize, null, game);
}
}
@ -682,21 +681,17 @@ public abstract class PlayerImpl implements Player, Serializable {
}
return discardedCards;
}
int numDiscarded = 0;
while (isInGame() && numDiscarded < amount) {
if (this.getHand().size() == 0) {
break;
if (random) {
for (int i = 0; i < amount; i++) {
Card card = this.getHand().getRandom(game);
discardedCards.add(card);
discard(card, source, game);
}
Card card;
if (random) {
card = this.getHand().getRandom(game);
} else {
TargetDiscard target = new TargetDiscard(playerId);
choose(Outcome.Discard, target, source.getSourceId(), game);
card = this.getHand().get(target.getFirstTarget(), game);
}
if (card != null) {
numDiscarded++;
} else {
TargetDiscard target = new TargetDiscard(amount, amount, new FilterCard(CardUtil.numberToText(amount, "a") + " card" + (amount > 1 ?"s":"")), playerId);
choose(Outcome.Discard, target, source == null?null:source.getSourceId(), game);
for (UUID cardId: target.getTargets()) {
Card card = this.getHand().get(cardId, game);
discardedCards.add(card);
discard(card, source, game);
}
@ -2253,36 +2248,40 @@ public abstract class PlayerImpl implements Player, Serializable {
return playable;
}
/**
* Creates a list of card ids that are currently playable.<br>
* Used to mark the playable cards in GameView
*
* @return A Set of cardIds that are playable
* @see mage.server.GameSessionPlayer#getGameView()
*
* @param game
*/
@Override
public Set<UUID> getPlayableInHand(Game game) {
Set<UUID> playable = new HashSet<>();
if (!shouldSkipGettingPlayable(game)) {
// for clean_up phase show all cards
if (game.getPhase() != null && PhaseStep.CLEANUP.equals(game.getPhase().getStep().getType())) {
for (Card card: hand.getCards(game)) {
playable.add(card.getId());
}
} else {
ManaOptions available = getManaAvailable(game);
available.addMana(manaPool.getMana());
ManaOptions available = getManaAvailable(game);
available.addMana(manaPool.getMana());
for (Card card : hand.getCards(game)) {
for (ActivatedAbility ability : card.getAbilities().getPlayableAbilities(Zone.HAND)) {
if (ability instanceof PlayLandAbility) {
if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) {
break;
}
}
if (canPlay(ability, available, card, game)) {
playable.add(card.getId());
for (Card card : hand.getCards(game)) {
for (ActivatedAbility ability : card.getAbilities().getPlayableAbilities(Zone.HAND)) {
if (ability instanceof PlayLandAbility) {
if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) {
break;
}
}
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
if (!playable.contains(ability.getSourceId()) && canPlay(ability, available, card, game)) {
playable.add(card.getId());
break;
}
if (canPlay(ability, available, card, game)) {
playable.add(card.getId());
break;
}
}
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
if (!playable.contains(ability.getSourceId()) && canPlay(ability, available, card, game)) {
playable.add(card.getId());
break;
}
}
}

View file

@ -28,6 +28,7 @@
package mage.target;
import java.io.Serializable;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.abilities.Ability;

View file

@ -62,7 +62,7 @@ public class TargetDiscard extends TargetCard {
super(minNumTargets, maxNumTargets, Zone.HAND, filter);
this.filter.add(new OwnerIdPredicate(playerId));
this.playerId = playerId;
this.targetName = "card to discard";
this.targetName = this.filter.getMessage() + " to discard";
}
public TargetDiscard(final TargetDiscard target) {