InputAttack appears a single time, players may click on entities they want to attack.

This commit is contained in:
Maxmtg
2013-04-22 08:31:33 +00:00
parent bc5f5aac51
commit a1440ed244
4 changed files with 85 additions and 68 deletions

View File

@@ -17,12 +17,15 @@
*/ */
package forge.control.input; package forge.control.input;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import forge.Card; import forge.Card;
import forge.CardPredicates; import forge.CardPredicates;
import forge.GameEntity;
import forge.Singletons; import forge.Singletons;
import forge.game.GameState; import forge.game.GameState;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
@@ -31,6 +34,7 @@ import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.framework.SDisplayUtil; import forge.gui.framework.SDisplayUtil;
import forge.gui.match.views.VMessage; import forge.gui.match.views.VMessage;
import forge.util.MyObservable;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
/** /**
@@ -45,7 +49,11 @@ public class InputAttack extends InputBase {
/** Constant <code>serialVersionUID=7849903731842214245L</code>. */ /** Constant <code>serialVersionUID=7849903731842214245L</code>. */
private static final long serialVersionUID = 7849903731842214245L; private static final long serialVersionUID = 7849903731842214245L;
private final GameState game; private final GameState game;
private List<GameEntity> defenders;
private GameEntity currentDefender;
public InputAttack(Player human) { public InputAttack(Player human) {
super(human); super(human);
game = human.getGame(); game = human.getGame();
@@ -58,24 +66,22 @@ public class InputAttack extends InputBase {
// TODO still seems to have some issues with multiple planeswalkers // TODO still seems to have some issues with multiple planeswalkers
ButtonUtil.enableOnlyOk(); ButtonUtil.enableOnlyOk();
defenders = game.getCombat().getDefenders();
setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0));
final Object o = game.getCombat().nextDefender(); if ( null == currentDefender ) {
if (o == null) { System.err.println("InputAttack has no potential defenders!");
return; return; // should even throw here!
} }
showMessage("Declare Attackers: Select Creatures to Attack " + o.toString()); List<Card> possibleAttackers = player.getCardsIn(ZoneType.Battlefield);
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) {
if (game.getCombat().getRemainingDefenders() == 0) { // last Target if (c.hasKeyword("CARDNAME attacks each turn if able.") && CombatUtil.canAttack(c, game.getCombat()) ) {
List<Card> possibleAttackers = player.getCardsIn(ZoneType.Battlefield); game.getCombat().addAttacker(c, currentDefender);
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) {
if (c.hasKeyword("CARDNAME attacks each turn if able.") && CombatUtil.canAttack(c, game.getCombat()) && !c.isAttacking()) {
game.getCombat().addAttacker(c);
}
} }
} }
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonOK() { public final void selectButtonOK() {
@@ -83,43 +89,53 @@ public class InputAttack extends InputBase {
game.getPhaseHandler().setCombat(); game.getPhaseHandler().setCombat();
} }
if (game.getCombat().getRemainingDefenders() != 0) { setCurrentDefender(null); // remove highlights
game.getPhaseHandler().repeatPhase();
}
game.getPhaseHandler().setPlayersPriorityPermission(false); game.getPhaseHandler().setPlayersPriorityPermission(false);
Singletons.getModel().getMatch().getInput().updateObservers(); Singletons.getModel().getMatch().getInput().updateObservers();
} }
@Override
public void selectPlayer(Player selected) {
if(player.isOpponentOf(selected))
setCurrentDefender(selected);
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectCard(final Card card, boolean isMetaDown) { public final void selectCard(final Card card, boolean isMetaDown) {
final List<Card> att = game.getCombat().getAttackers(); final List<Card> att = game.getCombat().getAttackers();
if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) { if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) {
card.untap();
game.getCombat().removeFromCombat(card); game.getCombat().removeFromCombat(card);
CombatUtil.showCombat(game); CombatUtil.showCombat(game);
return; return;
} }
if (card.isAttacking() || card.getController() != Singletons.getControl().getPlayer()) { if (card.isAttacking(currentDefender)) {
return; return;
} }
if ( card.getController().isOpponentOf(player) ) {
if ( defenders.contains(card) ) { // planeswalker?
setCurrentDefender(card);
return;
}
}
final Player human = Singletons.getControl().getPlayer();
Zone zone = game.getZoneOf(card); Zone zone = game.getZoneOf(card);
if (zone.is(ZoneType.Battlefield, human) if (zone.is(ZoneType.Battlefield, player) && CombatUtil.canAttack(card, game.getCombat())) {
&& CombatUtil.canAttack(card, game.getCombat())) {
// TODO add the propaganda code here and remove it in // TODO add the propaganda code here and remove it in
// Phase.nextPhase() // Phase.nextPhase()
// if (!CombatUtil.checkPropagandaEffects(card)) // if (!CombatUtil.checkPropagandaEffects(card))
// return; // return;
game.getCombat().addAttacker(card); if( game.getCombat().isAttacking(card)) {
game.getCombat().removeFromCombat(card);
}
game.getCombat().addAttacker(card, currentDefender);
// just to make sure the attack symbol is marked // just to make sure the attack symbol is marked
human.getZone(ZoneType.Battlefield).updateObservers(); player.getZone(ZoneType.Battlefield).updateObservers();
CombatUtil.showCombat(game); CombatUtil.showCombat(game);
ButtonUtil.enableOnlyOk(); ButtonUtil.enableOnlyOk();
} }
@@ -127,4 +143,26 @@ public class InputAttack extends InputBase {
SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE); SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE);
} }
} // selectCard() } // selectCard()
private final void setCurrentDefender(GameEntity def) {
Set<MyObservable> toUpdate = new HashSet<MyObservable>();
currentDefender = def;
for( GameEntity ge: defenders ) {
if ( ge instanceof Card) {
((Card) ge).setUsedToPay(ge == def);
toUpdate.add(((Card) ge).getController().getZone(ZoneType.Battlefield));
}
else if (ge instanceof Player) {
((Player) ge).setHighlited(ge == def);
toUpdate.add(ge);
}
}
showMessage("Declare Attackers.\nSelecting Creatures to Attack " + currentDefender + "\n\nTo attack other players or their planewalkers just click on them");
// This will instantly highlight targets
for(MyObservable updateable : toUpdate) {
updateable.updateObservers();
}
}
} }

View File

@@ -58,7 +58,7 @@ public class Combat {
private List<GameEntity> defenders = new ArrayList<GameEntity>(); private List<GameEntity> defenders = new ArrayList<GameEntity>();
private Map<GameEntity, List<Card>> defenderMap = new HashMap<GameEntity, List<Card>>(); private Map<GameEntity, List<Card>> defenderMap = new HashMap<GameEntity, List<Card>>();
private int currentDefender = 0; private int currentDefender = 0;
private int nextDefender = 0;
// This Hash keeps track of // This Hash keeps track of
private final HashMap<Card, GameEntity> attackerToDefender = new HashMap<Card, GameEntity>(); private final HashMap<Card, GameEntity> attackerToDefender = new HashMap<Card, GameEntity>();
@@ -88,7 +88,6 @@ public class Combat {
this.attackingPlayer = null; this.attackingPlayer = null;
this.currentDefender = 0; this.currentDefender = 0;
this.nextDefender = 0;
this.initiatePossibleDefenders(Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().getOpponents()); this.initiatePossibleDefenders(Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().getOpponents());
} }
@@ -126,24 +125,6 @@ public class Combat {
} }
} }
/**
* <p>
* nextDefender.
* </p>
*
* @return a {@link java.lang.Object} object.
*/
public final GameEntity nextDefender() {
if (this.nextDefender >= this.defenders.size()) {
return null;
}
this.currentDefender = this.nextDefender;
this.nextDefender++;
return this.defenders.get(this.currentDefender);
}
/** /**
* <p> * <p>
* getDefender. * getDefender.
@@ -178,17 +159,6 @@ public class Combat {
return this.currentDefender; return this.currentDefender;
} }
/**
* <p>
* getRemainingDefenders.
* </p>
*
* @return a int.
*/
public final int getRemainingDefenders() {
return this.defenders.size() - this.nextDefender;
}
/** /**
* <p> * <p>
* Getter for the field <code>defenders</code>. * Getter for the field <code>defenders</code>.

View File

@@ -3124,4 +3124,10 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
} }
} }
// These are used by UI to mark the player currently being attacked or targeted
// Very bad practice! Someone blame on me.
private boolean highlited = false;
public final void setHighlited(boolean value) { highlited = value; }
public final boolean isHighlited() { return highlited; }
} }

View File

@@ -30,6 +30,7 @@ import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder; import javax.swing.border.MatteBorder;
@@ -105,6 +106,11 @@ public class VField implements IVDoc<CField> {
private PhaseLabel lblEndTurn = new PhaseLabel("ET"); private PhaseLabel lblEndTurn = new PhaseLabel("ET");
private PhaseLabel lblCleanup = new PhaseLabel("CL"); private PhaseLabel lblCleanup = new PhaseLabel("CL");
private final Border borderAvatarSimple = new LineBorder(new Color(0, 0, 0, 0), 1);
private final Border borderAvatarHover = new LineBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS), 1);
private final Border borderAvatarHighlited = new LineBorder(Color.red, 2);
//========= Constructor //========= Constructor
/** /**
* Assembles Swing components of a player field instance. * Assembles Swing components of a player field instance.
@@ -144,13 +150,15 @@ public class VField implements IVDoc<CField> {
@Override @Override
public void mouseEntered(final MouseEvent e) { public void mouseEntered(final MouseEvent e) {
avatarArea.setOpaque(true); avatarArea.setOpaque(true);
avatarArea.setBorder(new LineBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS), 1)); if (!player.isHighlited())
avatarArea.setBorder(borderAvatarHover);
} }
@Override @Override
public void mouseExited(final MouseEvent e) { public void mouseExited(final MouseEvent e) {
avatarArea.setOpaque(false); avatarArea.setOpaque(false);
avatarArea.setBorder(new LineBorder(new Color(0, 0, 0, 0), 1)); if (!player.isHighlited())
avatarArea.setBorder(borderAvatarSimple);
} }
}); });
@@ -359,19 +367,14 @@ public class VField implements IVDoc<CField> {
this.getLblLife().setText("" + p0.getLife()); this.getLblLife().setText("" + p0.getLife());
this.getLblPoison().setText("" + p0.getPoisonCounters()); this.getLblPoison().setText("" + p0.getPoisonCounters());
if (p0.getLife() <= 5) { Color lifeFg = p0.getLife() <= 5 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT);
this.getLblLife().setForeground(Color.red); this.getLblLife().setForeground(lifeFg);
}
else {
this.getLblLife().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
}
if (p0.getPoisonCounters() >= 8) { Color poisonFg = p0.getPoisonCounters() >= 8 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT);
this.getLblPoison().setForeground(Color.red); this.getLblPoison().setForeground(poisonFg);
}
else { this.avatarArea.setBorder(p0.isHighlited() ? borderAvatarHighlited : borderAvatarSimple );
this.getLblPoison().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); this.avatarArea.setOpaque(p0.isHighlited());
}
} }
/** /**