mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
InputAttack appears a single time, players may click on entities they want to attack.
This commit is contained in:
@@ -17,12 +17,15 @@
|
||||
*/
|
||||
package forge.control.input;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardPredicates;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.game.GameState;
|
||||
import forge.game.phase.CombatUtil;
|
||||
@@ -31,6 +34,7 @@ import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.gui.match.views.VMessage;
|
||||
import forge.util.MyObservable;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
/**
|
||||
@@ -45,7 +49,11 @@ public class InputAttack extends InputBase {
|
||||
/** Constant <code>serialVersionUID=7849903731842214245L</code>. */
|
||||
private static final long serialVersionUID = 7849903731842214245L;
|
||||
|
||||
|
||||
private final GameState game;
|
||||
private List<GameEntity> defenders;
|
||||
private GameEntity currentDefender;
|
||||
|
||||
public InputAttack(Player human) {
|
||||
super(human);
|
||||
game = human.getGame();
|
||||
@@ -58,24 +66,22 @@ public class InputAttack extends InputBase {
|
||||
// TODO still seems to have some issues with multiple planeswalkers
|
||||
|
||||
ButtonUtil.enableOnlyOk();
|
||||
defenders = game.getCombat().getDefenders();
|
||||
setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0));
|
||||
|
||||
final Object o = game.getCombat().nextDefender();
|
||||
if (o == null) {
|
||||
return;
|
||||
if ( null == currentDefender ) {
|
||||
System.err.println("InputAttack has no potential defenders!");
|
||||
return; // should even throw here!
|
||||
}
|
||||
|
||||
showMessage("Declare Attackers: Select Creatures to Attack " + o.toString());
|
||||
|
||||
if (game.getCombat().getRemainingDefenders() == 0) { // last Target
|
||||
List<Card> possibleAttackers = player.getCardsIn(ZoneType.Battlefield);
|
||||
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);
|
||||
}
|
||||
List<Card> possibleAttackers = player.getCardsIn(ZoneType.Battlefield);
|
||||
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) {
|
||||
if (c.hasKeyword("CARDNAME attacks each turn if able.") && CombatUtil.canAttack(c, game.getCombat()) ) {
|
||||
game.getCombat().addAttacker(c, currentDefender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void selectButtonOK() {
|
||||
@@ -83,43 +89,53 @@ public class InputAttack extends InputBase {
|
||||
game.getPhaseHandler().setCombat();
|
||||
}
|
||||
|
||||
if (game.getCombat().getRemainingDefenders() != 0) {
|
||||
game.getPhaseHandler().repeatPhase();
|
||||
}
|
||||
|
||||
setCurrentDefender(null); // remove highlights
|
||||
game.getPhaseHandler().setPlayersPriorityPermission(false);
|
||||
Singletons.getModel().getMatch().getInput().updateObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectPlayer(Player selected) {
|
||||
if(player.isOpponentOf(selected))
|
||||
setCurrentDefender(selected);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void selectCard(final Card card, boolean isMetaDown) {
|
||||
final List<Card> att = game.getCombat().getAttackers();
|
||||
if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) {
|
||||
card.untap();
|
||||
game.getCombat().removeFromCombat(card);
|
||||
CombatUtil.showCombat(game);
|
||||
return;
|
||||
}
|
||||
|
||||
if (card.isAttacking() || card.getController() != Singletons.getControl().getPlayer()) {
|
||||
if (card.isAttacking(currentDefender)) {
|
||||
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);
|
||||
if (zone.is(ZoneType.Battlefield, human)
|
||||
&& CombatUtil.canAttack(card, game.getCombat())) {
|
||||
if (zone.is(ZoneType.Battlefield, player) && CombatUtil.canAttack(card, game.getCombat())) {
|
||||
|
||||
// TODO add the propaganda code here and remove it in
|
||||
// Phase.nextPhase()
|
||||
// if (!CombatUtil.checkPropagandaEffects(card))
|
||||
// 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
|
||||
human.getZone(ZoneType.Battlefield).updateObservers();
|
||||
player.getZone(ZoneType.Battlefield).updateObservers();
|
||||
CombatUtil.showCombat(game);
|
||||
ButtonUtil.enableOnlyOk();
|
||||
}
|
||||
@@ -127,4 +143,26 @@ public class InputAttack extends InputBase {
|
||||
SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE);
|
||||
}
|
||||
} // 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class Combat {
|
||||
private List<GameEntity> defenders = new ArrayList<GameEntity>();
|
||||
private Map<GameEntity, List<Card>> defenderMap = new HashMap<GameEntity, List<Card>>();
|
||||
private int currentDefender = 0;
|
||||
private int nextDefender = 0;
|
||||
|
||||
|
||||
// This Hash keeps track of
|
||||
private final HashMap<Card, GameEntity> attackerToDefender = new HashMap<Card, GameEntity>();
|
||||
@@ -88,7 +88,6 @@ public class Combat {
|
||||
|
||||
this.attackingPlayer = null;
|
||||
this.currentDefender = 0;
|
||||
this.nextDefender = 0;
|
||||
|
||||
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>
|
||||
* getDefender.
|
||||
@@ -178,17 +159,6 @@ public class Combat {
|
||||
return this.currentDefender;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getRemainingDefenders.
|
||||
* </p>
|
||||
*
|
||||
* @return a int.
|
||||
*/
|
||||
public final int getRemainingDefenders() {
|
||||
return this.defenders.size() - this.nextDefender;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>defenders</code>.
|
||||
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.LineBorder;
|
||||
import javax.swing.border.MatteBorder;
|
||||
|
||||
@@ -105,6 +106,11 @@ public class VField implements IVDoc<CField> {
|
||||
private PhaseLabel lblEndTurn = new PhaseLabel("ET");
|
||||
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
|
||||
/**
|
||||
* Assembles Swing components of a player field instance.
|
||||
@@ -144,13 +150,15 @@ public class VField implements IVDoc<CField> {
|
||||
@Override
|
||||
public void mouseEntered(final MouseEvent e) {
|
||||
avatarArea.setOpaque(true);
|
||||
avatarArea.setBorder(new LineBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS), 1));
|
||||
if (!player.isHighlited())
|
||||
avatarArea.setBorder(borderAvatarHover);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(final MouseEvent e) {
|
||||
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.getLblPoison().setText("" + p0.getPoisonCounters());
|
||||
|
||||
if (p0.getLife() <= 5) {
|
||||
this.getLblLife().setForeground(Color.red);
|
||||
}
|
||||
else {
|
||||
this.getLblLife().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
}
|
||||
Color lifeFg = p0.getLife() <= 5 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
||||
this.getLblLife().setForeground(lifeFg);
|
||||
|
||||
if (p0.getPoisonCounters() >= 8) {
|
||||
this.getLblPoison().setForeground(Color.red);
|
||||
}
|
||||
else {
|
||||
this.getLblPoison().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||
}
|
||||
Color poisonFg = p0.getPoisonCounters() >= 8 ? Color.red : FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
||||
this.getLblPoison().setForeground(poisonFg);
|
||||
|
||||
this.avatarArea.setBorder(p0.isHighlited() ? borderAvatarHighlited : borderAvatarSimple );
|
||||
this.avatarArea.setOpaque(p0.isHighlited());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user