mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
- Human may now declare attacks in a band
- Added Benalish Hero
This commit is contained in:
@@ -206,6 +206,16 @@ public class Combat {
|
||||
public final List<Card> getAttackersOf(GameEntity defender) {
|
||||
return defenderMap.get(defender);
|
||||
}
|
||||
|
||||
public final List<AttackingBand> getAttackingBandsOf(GameEntity defender) {
|
||||
List<AttackingBand> bands = new ArrayList<AttackingBand>();
|
||||
for(AttackingBand band : this.attackingBands) {
|
||||
if (band.getDefender().equals(defender)) {
|
||||
bands.add(band);
|
||||
}
|
||||
}
|
||||
return bands;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -503,11 +513,17 @@ public class Combat {
|
||||
this.blockerToBandsMap.get(b).remove(c);
|
||||
}
|
||||
// Clear removed attacker from assignment order
|
||||
this.blockerDamageAssignmentOrder.get(b).remove(c);
|
||||
if (this.blockerDamageAssignmentOrder.containsKey(b)) {
|
||||
this.blockerDamageAssignmentOrder.get(b).remove(c);
|
||||
}
|
||||
}
|
||||
|
||||
this.defenderMap.get(band.getDefender()).remove(c);
|
||||
} else if (this.blockerDamageAssignmentOrder.containsKey(c)) { // card is a blocker
|
||||
|
||||
if (band.getAttackers().isEmpty() && band.getBlockers().isEmpty()) {
|
||||
this.getAttackingBands().remove(band);
|
||||
}
|
||||
} else if (this.blockerToBandsMap.containsKey(c)) { // card is a blocker
|
||||
List<AttackingBand> attackers = this.blockerToBandsMap.get(c);
|
||||
|
||||
this.blockerToBandsMap.remove(c);
|
||||
@@ -515,7 +531,9 @@ public class Combat {
|
||||
for (AttackingBand a : attackers) {
|
||||
a.removeBlocker(c);
|
||||
for(Card atk : a.getAttackers()) {
|
||||
this.attackerDamageAssignmentOrder.get(atk).remove(c);
|
||||
if (this.attackerDamageAssignmentOrder.containsKey(atk)) {
|
||||
this.attackerDamageAssignmentOrder.get(atk).remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.google.common.collect.Iterables;
|
||||
import forge.Card;
|
||||
import forge.CardPredicates;
|
||||
import forge.GameEntity;
|
||||
import forge.game.combat.AttackingBand;
|
||||
import forge.game.phase.Combat;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.player.Player;
|
||||
@@ -52,6 +53,7 @@ public class InputAttack extends InputSyncronizedBase {
|
||||
private GameEntity currentDefender;
|
||||
private final Player playerAttacks;
|
||||
private final Player playerDeclares;
|
||||
private AttackingBand activeBand = null;
|
||||
|
||||
public InputAttack(Player attacks, Player declares, Combat combat) {
|
||||
this.playerAttacks = attacks;
|
||||
@@ -97,8 +99,10 @@ public class InputAttack extends InputSyncronizedBase {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected final void onOk() {
|
||||
// TODO Add check to see if each must attack creature is attacking
|
||||
// Propaganda costs could have been paid here.
|
||||
setCurrentDefender(null); // remove highlights
|
||||
activateBand(null);
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -115,12 +119,33 @@ public class InputAttack extends InputSyncronizedBase {
|
||||
protected final void onCardSelected(final Card card, boolean isMetaDown) {
|
||||
final List<Card> att = combat.getAttackers();
|
||||
if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) {
|
||||
// TODO Is there no way to attacks each turn cards to attack Planeswalkers?
|
||||
combat.removeFromCombat(card);
|
||||
card.setUsedToPay(false);
|
||||
showCombat();
|
||||
// When removing an attacker should I clear the attacking band?
|
||||
this.activateBand(this.activeBand);
|
||||
return;
|
||||
}
|
||||
|
||||
if (card.isAttacking(currentDefender)) {
|
||||
// Activate band by selecting/deselecting a band member
|
||||
if (this.activeBand == null) {
|
||||
this.activateBand(combat.getBandByAttacker(card));
|
||||
} else if (this.activeBand.getAttackers().contains(card)) {
|
||||
this.activateBand(null);
|
||||
} else { // Join a band by selecting a non-active band member after activating a band
|
||||
if (this.activeBand.canJoinBand(card)) {
|
||||
combat.removeFromCombat(card);
|
||||
combat.addAttacker(card, currentDefender, this.activeBand);
|
||||
this.activateBand(this.activeBand);
|
||||
updateMessage();
|
||||
} else {
|
||||
flashIncorrectAction();
|
||||
}
|
||||
}
|
||||
|
||||
updateMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,10 +157,20 @@ public class InputAttack extends InputSyncronizedBase {
|
||||
}
|
||||
|
||||
if (playerAttacks.getZone(ZoneType.Battlefield).contains(card) && CombatUtil.canAttack(card, currentDefender, combat)) {
|
||||
if( combat.isAttacking(card)) {
|
||||
combat.removeFromCombat(card);
|
||||
if (this.activeBand != null && !this.activeBand.canJoinBand(card)) {
|
||||
this.activateBand(null);
|
||||
updateMessage();
|
||||
flashIncorrectAction();
|
||||
return;
|
||||
}
|
||||
combat.addAttacker(card, currentDefender);
|
||||
|
||||
if(combat.isAttacking(card)) {
|
||||
combat.removeFromCombat(card);
|
||||
}
|
||||
|
||||
combat.addAttacker(card, currentDefender, this.activeBand);
|
||||
this.activateBand(this.activeBand);
|
||||
updateMessage();
|
||||
showCombat();
|
||||
}
|
||||
else {
|
||||
@@ -157,13 +192,45 @@ public class InputAttack extends InputSyncronizedBase {
|
||||
}
|
||||
}
|
||||
|
||||
String header = playerAttacks == playerDeclares ? "declare attackers." : "declare attackers for " + playerAttacks.getName();
|
||||
showMessage(playerDeclares.getName() + ", " + header + "\nSelecting Creatures to Attack " + currentDefender +
|
||||
"\n\nTo attack other players or their planewalkers just click on them");
|
||||
updateMessage();
|
||||
|
||||
// This will instantly highlight targets
|
||||
for(MyObservable updateable : toUpdate) {
|
||||
updateable.updateObservers();
|
||||
}
|
||||
}
|
||||
|
||||
private final void activateBand(AttackingBand band) {
|
||||
Set<MyObservable> toUpdate = new HashSet<MyObservable>();
|
||||
if (this.activeBand != null) {
|
||||
for(Card card : this.activeBand.getAttackers()) {
|
||||
card.setUsedToPay(false);
|
||||
toUpdate.add(card.getController().getZone(ZoneType.Battlefield));
|
||||
}
|
||||
}
|
||||
this.activeBand = band;
|
||||
|
||||
if (this.activeBand != null) {
|
||||
for(Card card : this.activeBand.getAttackers()) {
|
||||
card.setUsedToPay(true);
|
||||
toUpdate.add(card.getController().getZone(ZoneType.Battlefield));
|
||||
}
|
||||
}
|
||||
|
||||
// This will instantly highlight targets
|
||||
for(MyObservable updateable : toUpdate) {
|
||||
updateable.updateObservers();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMessage() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(playerDeclares.getName()).append(", ");
|
||||
sb.append(playerAttacks == playerDeclares ? "declare attackers." : "declare attackers for " + playerAttacks.getName()).append("\n");
|
||||
sb.append("Selecting Creatures to Attack ").append(currentDefender).append("\n\n");
|
||||
sb.append("To change the current defender, click on the player or planeswalker you wish to attack.\n");
|
||||
sb.append("To attack as a band, click an attacking creature to activate its 'band', select another to join the band.");
|
||||
|
||||
showMessage(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import forge.Card;
|
||||
import forge.Command;
|
||||
import forge.GameEntity;
|
||||
import forge.game.Game;
|
||||
import forge.game.combat.AttackingBand;
|
||||
import forge.game.phase.Combat;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -70,8 +71,8 @@ public enum CCombat implements ICDoc {
|
||||
|
||||
// Not a big fan of the triple nested loop here
|
||||
for (GameEntity defender : combat.getDefenders()) {
|
||||
List<Card> atk = combat.getAttackersOf(defender);
|
||||
if (atk == null || atk.isEmpty()) {
|
||||
List<AttackingBand> bands = combat.getAttackingBandsOf(defender);
|
||||
if (bands == null || bands.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -86,18 +87,23 @@ public enum CCombat implements ICDoc {
|
||||
|
||||
display.append(defender.getName()).append(" is attacked by:\n");
|
||||
|
||||
for (final Card c : atk) {
|
||||
// loop through attackers
|
||||
display.append(" > ");
|
||||
display.append(combatantToString(c)).append("\n");
|
||||
// Associate Bands, Attackers Blockers
|
||||
for(AttackingBand band : bands) {
|
||||
display.append(" BAND");
|
||||
if (band.getBlocked()) {
|
||||
display.append(" (blocked)");
|
||||
}
|
||||
display.append("\n");
|
||||
|
||||
for (final Card c : band.getAttackers()) {
|
||||
display.append(" > ");
|
||||
display.append(combatantToString(c)).append("\n");
|
||||
}
|
||||
|
||||
List<Card> blockers = combat.getBlockers(c, true);
|
||||
|
||||
// loop through blockers
|
||||
for (final Card element : blockers) {
|
||||
for (final Card element : band.getBlockers()) {
|
||||
display.append(" < ").append(combatantToString(element)).append("\n");
|
||||
}
|
||||
} // loop through attackers
|
||||
}
|
||||
}
|
||||
return display.toString().trim();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user