mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
made distribute damage method return Map<Card, int> as decisions taken by player, combat.java now does not depend on player type and has no GUI references
This commit is contained in:
@@ -1642,15 +1642,18 @@ public class ComputerUtilCombat {
|
||||
* @param damage
|
||||
* a int.
|
||||
*/
|
||||
public static void distributeAIDamage(final Card attacker, final List<Card> block, int damage, Combat combat) {
|
||||
public static Map<Card, Integer> distributeAIDamage(final Card attacker, final List<Card> block, int damage) {
|
||||
final Card c = attacker;
|
||||
|
||||
Map<Card, Integer> damageMap = new HashMap<Card, Integer>();
|
||||
|
||||
if (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|
||||
|| attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")) {
|
||||
combat.addDefendingDamage(damage, attacker);
|
||||
return;
|
||||
damageMap.put(null, damage);
|
||||
return damageMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
final boolean hasTrample = attacker.hasKeyword("Trample");
|
||||
|
||||
if (block.size() == 1) {
|
||||
@@ -1678,12 +1681,12 @@ public class ComputerUtilCombat {
|
||||
// If Extra trample damage, assign to defending
|
||||
// player/planeswalker
|
||||
if (0 < trample) {
|
||||
combat.addDefendingDamage(trample, attacker);
|
||||
damageMap.put(null, trample);
|
||||
}
|
||||
|
||||
blocker.addAssignedDamage(damageNeeded, attacker);
|
||||
damageMap.put(blocker, damageNeeded);
|
||||
} else {
|
||||
blocker.addAssignedDamage(damage, attacker);
|
||||
damageMap.put(blocker, damage);
|
||||
}
|
||||
} // 1 blocker
|
||||
else {
|
||||
@@ -1695,10 +1698,7 @@ public class ComputerUtilCombat {
|
||||
final int enoughDamageToKill = ComputerUtilCombat.getEnoughDamageToKill(b, damage, attacker, true);
|
||||
if (enoughDamageToKill <= damage) {
|
||||
damage -= enoughDamageToKill;
|
||||
final List<Card> cl = new ArrayList<Card>();
|
||||
cl.add(attacker);
|
||||
|
||||
b.addAssignedDamage(enoughDamageToKill, c);
|
||||
damageMap.put(b, enoughDamageToKill);
|
||||
} else {
|
||||
killsAllBlockers = false;
|
||||
}
|
||||
@@ -1708,13 +1708,14 @@ public class ComputerUtilCombat {
|
||||
if (killsAllBlockers && damage > 0) {
|
||||
// if attacker has no trample, and there's damage left, assign the rest to the last blocker
|
||||
if (!hasTrample && lastBlocker != null) {
|
||||
lastBlocker.addAssignedDamage(damage, c);
|
||||
damageMap.put(lastBlocker, damage);
|
||||
damage = 0;
|
||||
} else if (hasTrample) {
|
||||
combat.addDefendingDamage(damage, c);
|
||||
damageMap.put(null, damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return damageMap;
|
||||
} // setAssignedDamage()
|
||||
|
||||
|
||||
|
||||
@@ -33,12 +33,9 @@ import forge.CardPredicates;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.card.trigger.TriggerType;
|
||||
import forge.game.ai.ComputerUtilCombat;
|
||||
import forge.game.event.BlockerAssignedEvent;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiDialog;
|
||||
import forge.gui.match.CMatchUI;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -695,14 +692,10 @@ public class Combat {
|
||||
|
||||
if (!attackers.isEmpty()) {
|
||||
assignedDamage = true;
|
||||
if (blocker.getController().isHuman()) { // who is defending matters
|
||||
if (attackers.size() > 1) {
|
||||
CMatchUI.SINGLETON_INSTANCE.assignDamage(blocker, attackers, damage, null);
|
||||
} else {
|
||||
attackers.get(0).addAssignedDamage(damage, blocker);
|
||||
}
|
||||
} else { // computer attacks
|
||||
ComputerUtilCombat.distributeAIDamage(blocker, attackers, damage, this);
|
||||
Map<Card, Integer> map = blocker.getController().getController().assignCombatDamage(blocker, attackers, damage, null);
|
||||
for (Entry<Card, Integer> dt : map.entrySet()) {
|
||||
dt.getKey().addAssignedDamage(dt.getValue(), blocker);
|
||||
dt.getKey().updateObservers();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,12 +704,6 @@ public class Combat {
|
||||
return assignedDamage;
|
||||
}
|
||||
|
||||
private final boolean assignDamageAsIfNotBlocked(Card attacker) {
|
||||
return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")
|
||||
|| (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|
||||
&& GuiDialog.confirm(attacker, "Do you want to assign its combat damage as though it weren't blocked?"));
|
||||
}
|
||||
|
||||
private final boolean assignAttackersDamage(boolean firstStrikeDamage) {
|
||||
this.defendingDamageMap.clear(); // this should really happen in deal damage
|
||||
List<Card> blockers = null;
|
||||
@@ -746,19 +733,17 @@ public class Combat {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (this.getAttackingPlayer().isHuman()) { // human attacks
|
||||
if (assignDamageAsIfNotBlocked(attacker)) {
|
||||
this.addDefendingDamage(damageDealt, attacker);
|
||||
Map<Card, Integer> map = this.getAttackingPlayer().getController().assignCombatDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker));
|
||||
for (Entry<Card, Integer> dt : map.entrySet()) {
|
||||
if( dt.getKey() == null && trampler) {
|
||||
if (dt.getValue() > 0)
|
||||
addDefendingDamage(dt.getValue(), attacker);
|
||||
} else {
|
||||
if (trampler || (blockers.size() > 1)) {
|
||||
CMatchUI.SINGLETON_INSTANCE.assignDamage(attacker, blockers, damageDealt, this.getDefenderByAttacker(attacker));
|
||||
} else {
|
||||
blockers.get(0).addAssignedDamage(damageDealt, attacker);
|
||||
}
|
||||
dt.getKey().addAssignedDamage(dt.getValue(), attacker);
|
||||
dt.getKey().updateObservers();
|
||||
}
|
||||
} else { // computer attacks
|
||||
ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt, this);
|
||||
}
|
||||
|
||||
} // if !hasFirstStrike ...
|
||||
} // for
|
||||
return assignedDamage;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package forge.game.player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
@@ -88,4 +90,6 @@ public abstract class PlayerController {
|
||||
public abstract Deck sideboard(final Deck deck, GameType gameType);
|
||||
|
||||
|
||||
public abstract Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package forge.game.player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.GameEntity;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
@@ -13,6 +15,7 @@ import forge.game.ai.AiController;
|
||||
import forge.game.ai.AiInputBlock;
|
||||
import forge.game.ai.AiInputCommon;
|
||||
import forge.game.ai.ComputerUtil;
|
||||
import forge.game.ai.ComputerUtilCombat;
|
||||
import forge.gui.GuiChoose;
|
||||
|
||||
|
||||
@@ -160,6 +163,14 @@ public class PlayerControllerAi extends PlayerController {
|
||||
return deck;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.player.PlayerController#assignCombatDamage(forge.Card, java.util.List, int, forge.GameEntity)
|
||||
*/
|
||||
@Override
|
||||
public Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender) {
|
||||
return ComputerUtilCombat.distributeAIDamage(attacker, blockers, damageDealt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package forge.game.player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import forge.Card;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
@@ -170,6 +173,32 @@ public class PlayerControllerHuman extends PlayerController {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.player.PlayerController#assignCombatDamage()
|
||||
*/
|
||||
@Override
|
||||
public Map<Card, Integer> assignCombatDamage(Card attacker, List<Card> blockers, int damageDealt, GameEntity defender) {
|
||||
Map<Card, Integer> map;
|
||||
if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
|
||||
map = new HashMap<Card, Integer>();
|
||||
map.put(null, damageDealt);
|
||||
} else {
|
||||
if (attacker.hasKeyword("Trample") || (blockers.size() > 1)) {
|
||||
map = CMatchUI.SINGLETON_INSTANCE.getDamageToAssign(attacker, blockers, damageDealt, defender);
|
||||
} else {
|
||||
map = new HashMap<Card, Integer>();
|
||||
map.put(blockers.get(0), damageDealt);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private final boolean assignDamageAsIfNotBlocked(Card attacker) {
|
||||
return attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")
|
||||
|| (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|
||||
&& GuiDialog.confirm(attacker, "Do you want to assign its combat damage as though it weren't blocked?"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ package forge.gui.match;
|
||||
import java.awt.Image;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
@@ -186,19 +188,22 @@ public enum CMatchUI implements CardContainer {
|
||||
* @param blockers   {@link forge.CardList}
|
||||
* @param damage   int
|
||||
*/
|
||||
public void assignDamage(final Card attacker, final List<Card> blockers, final int damage, GameEntity defender) {
|
||||
public Map<Card, Integer> getDamageToAssign(final Card attacker, final List<Card> blockers, final int damage, GameEntity defender) {
|
||||
if (damage <= 0) {
|
||||
return;
|
||||
return new HashMap<Card, Integer>();
|
||||
}
|
||||
|
||||
// If the first blocker can absorb all of the damage, don't show the Assign Damage Frame
|
||||
Card firstBlocker = blockers.get(0);
|
||||
if (!attacker.hasKeyword("Deathtouch") && firstBlocker.getLethalDamage() >= damage) {
|
||||
firstBlocker.addAssignedDamage(damage, attacker);
|
||||
return;
|
||||
Map<Card, Integer> res = new HashMap<Card, Integer>();
|
||||
res.put(firstBlocker, damage);
|
||||
return res;
|
||||
}
|
||||
|
||||
new VAssignDamage(attacker, blockers, damage, defender);
|
||||
VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender);
|
||||
return v.getDamageMap();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,6 @@ import net.miginfocom.swing.MigLayout;
|
||||
import forge.Card;
|
||||
import forge.CounterType;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.game.MatchController;
|
||||
import forge.game.player.Player;
|
||||
import forge.gui.SOverlayUtils;
|
||||
@@ -66,7 +65,6 @@ public class VAssignDamage {
|
||||
// Damage storage
|
||||
private final int totalDamageToAssign;
|
||||
|
||||
private final Card attacker;
|
||||
private boolean attackerHasDeathtouch = false;
|
||||
private boolean attackerHasTrample = false;
|
||||
private boolean attackerHasInfect = false;
|
||||
@@ -106,12 +104,11 @@ public class VAssignDamage {
|
||||
}
|
||||
|
||||
// Mouse actions
|
||||
private final MouseAdapter madDefender = new MouseAdapter() {
|
||||
private final MouseAdapter mad = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(final MouseEvent evt) {
|
||||
Card source = ((CardPanel) evt.getSource()).getCard();
|
||||
if (!damage.containsKey(source))
|
||||
source = null;
|
||||
if (!damage.containsKey(source)) source = null; // to get player instead of fake card
|
||||
|
||||
FSkin.Colors brdrColor = VAssignDamage.this.canAssignTo(source) ? FSkin.Colors.CLR_ACTIVE : FSkin.Colors.CLR_INACTIVE;
|
||||
((CardPanel) evt.getSource()).setBorder(new LineBorder(FSkin.getColor(brdrColor), 2));
|
||||
@@ -149,7 +146,6 @@ public class VAssignDamage {
|
||||
this.attackerHasDeathtouch = attacker0.hasKeyword("Deathtouch");
|
||||
this.attackerHasInfect = attacker0.hasKeyword("Infect");
|
||||
this.attackerHasTrample = defender != null && attacker0.hasKeyword("Trample");
|
||||
this.attacker = attacker0;
|
||||
|
||||
// Top-level UI stuff
|
||||
final JPanel overlay = SOverlayUtils.genericOverlay();
|
||||
@@ -257,7 +253,7 @@ public class VAssignDamage {
|
||||
cp.setCardBounds(0, 0, 105, 150);
|
||||
cp.setOpaque(true);
|
||||
pnlDefenders.add(cp, "w 145px!, h 170px!, gap 5px 5px 3px 3px, ax center");
|
||||
cp.addMouseListener(madDefender);
|
||||
cp.addMouseListener(mad);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,15 +392,6 @@ public class VAssignDamage {
|
||||
if ( getRemainingDamage() > 0 )
|
||||
return;
|
||||
|
||||
for (DamageTarget dt : defenders) {
|
||||
if( dt.card == null && attackerHasTrample ) {
|
||||
Singletons.getModel().getGame().getCombat().addDefendingDamage(dt.damage, this.attacker);
|
||||
continue;
|
||||
}
|
||||
dt.card.addAssignedDamage(dt.damage, this.attacker);
|
||||
dt.card.updateObservers();
|
||||
}
|
||||
|
||||
dlg.dispose();
|
||||
SOverlayUtils.hideOverlay();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user