mirror of
https://github.com/correl/mage.git
synced 2024-12-26 19:16:54 +00:00
Dealing combat damage at the same time. Fixed Issue 236. Note: implemented only for damage resultings.
This commit is contained in:
parent
c207060611
commit
2e97eb38fd
4 changed files with 99 additions and 28 deletions
|
@ -146,7 +146,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
return perm.getAbilities().containsKey(TrampleAbility.getInstance().getId());
|
return perm.getAbilities().containsKey(TrampleAbility.getInstance().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignDamage(boolean first, Game game) {
|
public void assignDamageToBlockers(boolean first, Game game) {
|
||||||
if (attackers.size() > 0 && (!first || hasFirstOrDoubleStrike(game))) {
|
if (attackers.size() > 0 && (!first || hasFirstOrDoubleStrike(game))) {
|
||||||
if (blockers.size() == 0) {
|
if (blockers.size() == 0) {
|
||||||
unblockedDamage(first, game);
|
unblockedDamage(first, game);
|
||||||
|
@ -171,6 +171,21 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void applyDamage(Game game) {
|
||||||
|
for (UUID uuid : attackers) {
|
||||||
|
Permanent permanent = game.getPermanent(uuid);
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.applyDamage(game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (UUID uuid : blockers) {
|
||||||
|
Permanent permanent = game.getPermanent(uuid);
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.applyDamage(game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if permanent can damage in current (First Strike or not) combat damage step
|
* Determines if permanent can damage in current (First Strike or not) combat damage step
|
||||||
*
|
*
|
||||||
|
@ -218,25 +233,25 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
if (hasTrample(attacker)) {
|
if (hasTrample(attacker)) {
|
||||||
int lethalDamage = blocker.getToughness().getValue() - blocker.getDamage();
|
int lethalDamage = blocker.getToughness().getValue() - blocker.getDamage();
|
||||||
if (lethalDamage >= damage) {
|
if (lethalDamage >= damage) {
|
||||||
blocker.damage(damage, attacker.getId(), game, true, true);
|
blocker.markDamage(damage, attacker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Player player = game.getPlayer(attacker.getControllerId());
|
Player player = game.getPlayer(attacker.getControllerId());
|
||||||
int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game);
|
int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game);
|
||||||
blocker.damage(damageAssigned, attacker.getId(), game, true, true);
|
blocker.markDamage(damageAssigned, attacker.getId(), game, true, true);
|
||||||
damage -= damageAssigned;
|
damage -= damageAssigned;
|
||||||
if (damage > 0)
|
if (damage > 0)
|
||||||
defenderDamage(attacker, damage, game);
|
defenderDamage(attacker, damage, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
blocker.damage(damage, attacker.getId(), game, true, true);
|
blocker.markDamage(damage, attacker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (canDamage(blocker, first)) {
|
if (canDamage(blocker, first)) {
|
||||||
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
||||||
int blockerDamage = blocker.getPower().getValue();
|
int blockerDamage = blocker.getPower().getValue();
|
||||||
attacker.damage(blockerDamage, blocker.getId(), game, true, true);
|
attacker.markDamage(blockerDamage, blocker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,21 +294,21 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
Permanent blocker = game.getPermanent(blockerId);
|
Permanent blocker = game.getPermanent(blockerId);
|
||||||
if (canDamage(blocker, first)) {
|
if (canDamage(blocker, first)) {
|
||||||
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
||||||
attacker.damage(blocker.getPower().getValue(), blocker.getId(), game, true, true);
|
attacker.markDamage(blocker.getPower().getValue(), blocker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Issue#73
|
// Issue#73
|
||||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||||
Permanent blocker = game.getPermanent(entry.getKey());
|
Permanent blocker = game.getPermanent(entry.getKey());
|
||||||
blocker.damage(entry.getValue(), attacker.getId(), game, true, true);
|
blocker.markDamage(entry.getValue(), attacker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (UUID blockerId: blockerOrder) {
|
for (UUID blockerId: blockerOrder) {
|
||||||
Permanent blocker = game.getPermanent(blockerId);
|
Permanent blocker = game.getPermanent(blockerId);
|
||||||
if (canDamage(blocker, first)) {
|
if (canDamage(blocker, first)) {
|
||||||
attacker.damage(blocker.getPower().getValue(), blocker.getId(), game, true, true);
|
attacker.markDamage(blocker.getPower().getValue(), blocker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +329,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
if (blocker != null && attacker != null) {
|
if (blocker != null && attacker != null) {
|
||||||
if (canDamage(blocker, first)) {
|
if (canDamage(blocker, first)) {
|
||||||
int damage = blocker.getPower().getValue();
|
int damage = blocker.getPower().getValue();
|
||||||
attacker.damage(damage, blocker.getId(), game, true, true);
|
attacker.markDamage(damage, blocker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +372,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
|
|
||||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||||
Permanent attacker = game.getPermanent(entry.getKey());
|
Permanent attacker = game.getPermanent(entry.getKey());
|
||||||
attacker.damage(entry.getValue(), blocker.getId(), game, true, true);
|
attacker.markDamage(entry.getValue(), blocker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,7 +381,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
||||||
if (this.defenderIsPlaneswalker) {
|
if (this.defenderIsPlaneswalker) {
|
||||||
Permanent defender = game.getPermanent(defenderId);
|
Permanent defender = game.getPermanent(defenderId);
|
||||||
if (defender != null) {
|
if (defender != null) {
|
||||||
defender.damage(amount, attacker.getId(), game, true, true);
|
defender.markDamage(amount, attacker.getId(), game, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -75,6 +75,11 @@ public interface Permanent extends Card {
|
||||||
public boolean hasSummoningSickness();
|
public boolean hasSummoningSickness();
|
||||||
public int getDamage();
|
public int getDamage();
|
||||||
public int damage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
|
public int damage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
|
||||||
|
|
||||||
|
// used in combat only to deal damage at the same time
|
||||||
|
public int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
|
||||||
|
public int applyDamage(Game game);
|
||||||
|
|
||||||
public void removeAllDamage(Game game);
|
public void removeAllDamage(Game game);
|
||||||
public Counters getCounters();
|
public Counters getCounters();
|
||||||
public void addCounters(String name, int amount, Game game);
|
public void addCounters(String name, int amount, Game game);
|
||||||
|
|
|
@ -44,10 +44,8 @@ import mage.game.events.*;
|
||||||
import mage.game.events.GameEvent.EventType;
|
import mage.game.events.GameEvent.EventType;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.Constants.AsThoughEffectType;
|
import mage.Constants.AsThoughEffectType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,6 +76,7 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
||||||
protected List<UUID> connectedCards = new ArrayList<UUID>();
|
protected List<UUID> connectedCards = new ArrayList<UUID>();
|
||||||
protected List<UUID> dealtDamageByThisTurn;
|
protected List<UUID> dealtDamageByThisTurn;
|
||||||
protected UUID attachedTo;
|
protected UUID attachedTo;
|
||||||
|
protected List<Counter> markedDamage;
|
||||||
|
|
||||||
private static final List<UUID> emptyList = Collections.unmodifiableList(new ArrayList<UUID>());
|
private static final List<UUID> emptyList = Collections.unmodifiableList(new ArrayList<UUID>());
|
||||||
|
|
||||||
|
@ -126,6 +125,12 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
||||||
for (UUID sourceId : permanent.dealtDamageByThisTurn) {
|
for (UUID sourceId : permanent.dealtDamageByThisTurn) {
|
||||||
this.dealtDamageByThisTurn.add(sourceId);
|
this.dealtDamageByThisTurn.add(sourceId);
|
||||||
}
|
}
|
||||||
|
if (permanent.markedDamage != null) {
|
||||||
|
markedDamage = new ArrayList<Counter>();
|
||||||
|
for (Counter counter : permanent.markedDamage) {
|
||||||
|
markedDamage.add(counter.copy());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.attachedTo = permanent.attachedTo;
|
this.attachedTo = permanent.attachedTo;
|
||||||
this.minBlockedBy = permanent.minBlockedBy;
|
this.minBlockedBy = permanent.minBlockedBy;
|
||||||
|
@ -505,12 +510,26 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat) {
|
public int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat) {
|
||||||
|
return damage(damageAmount, sourceId, game, preventable, combat, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param damageAmount
|
||||||
|
* @param sourceId
|
||||||
|
* @param game
|
||||||
|
* @param preventable
|
||||||
|
* @param combat
|
||||||
|
* @param markDamage If true, damage will be dealt later in applyDamage method
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage) {
|
||||||
int damageDone = 0;
|
int damageDone = 0;
|
||||||
if (damageAmount > 0 && canDamage(game.getObject(sourceId))) {
|
if (damageAmount > 0 && canDamage(game.getObject(sourceId))) {
|
||||||
if (cardType.contains(CardType.PLANESWALKER)) {
|
if (cardType.contains(CardType.PLANESWALKER)) {
|
||||||
damageDone = damagePlaneswalker(damageAmount, sourceId, game, preventable, combat);
|
damageDone = damagePlaneswalker(damageAmount, sourceId, game, preventable, combat, markDamage);
|
||||||
} else {
|
} else {
|
||||||
damageDone = damageCreature(damageAmount, sourceId, game, preventable, combat);
|
damageDone = damageCreature(damageAmount, sourceId, game, preventable, combat, markDamage);
|
||||||
}
|
}
|
||||||
if (damageDone > 0) {
|
if (damageDone > 0) {
|
||||||
Permanent source = game.getPermanent(sourceId);
|
Permanent source = game.getPermanent(sourceId);
|
||||||
|
@ -530,13 +549,31 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
||||||
return damageDone;
|
return damageDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int markDamage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat) {
|
||||||
|
return damage(damageAmount, sourceId, game, preventable, combat, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int applyDamage(Game game) {
|
||||||
|
if (markedDamage == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (Counter counter : markedDamage) {
|
||||||
|
addCounters(counter, game);
|
||||||
|
}
|
||||||
|
markedDamage.clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAllDamage(Game game) {
|
public void removeAllDamage(Game game) {
|
||||||
damage = 0;
|
damage = 0;
|
||||||
deathtouched = false;
|
deathtouched = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat) {
|
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage) {
|
||||||
GameEvent event = new DamagePlaneswalkerEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
GameEvent event = new DamagePlaneswalkerEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
||||||
if (!game.replaceEvent(event)) {
|
if (!game.replaceEvent(event)) {
|
||||||
int actualDamage = event.getAmount();
|
int actualDamage = event.getAmount();
|
||||||
|
@ -553,23 +590,22 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat) {
|
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage) {
|
||||||
GameEvent event = new DamageCreatureEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
GameEvent event = new DamageCreatureEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
||||||
if (!game.replaceEvent(event)) {
|
if (!game.replaceEvent(event)) {
|
||||||
int actualDamage = event.getAmount();
|
int actualDamage = event.getAmount();
|
||||||
if (actualDamage > 0) {
|
if (actualDamage > 0) {
|
||||||
// this is not correct
|
|
||||||
// from rules: The amount of damage dealt to a creature is not bounded by its toughness,
|
|
||||||
// and the amount of damage dealt to a player is not bounded by that player's life total.
|
|
||||||
// For example, if Corrupt deals 6 damage to a 2/2 creature, you'll gain 6 life.
|
|
||||||
/*if (this.damage + event.getAmount() > this.toughness.getValue()) {
|
|
||||||
actualDamage = this.toughness.getValue() - this.damage;
|
|
||||||
}*/
|
|
||||||
//Permanent source = game.getPermanent(sourceId);
|
//Permanent source = game.getPermanent(sourceId);
|
||||||
MageObject source = game.getObject(sourceId);
|
MageObject source = game.getObject(sourceId);
|
||||||
if (source != null && (source.getAbilities().containsKey(InfectAbility.getInstance().getId())
|
if (source != null && (source.getAbilities().containsKey(InfectAbility.getInstance().getId())
|
||||||
|| source.getAbilities().containsKey(WitherAbility.getInstance().getId()))) {
|
|| source.getAbilities().containsKey(WitherAbility.getInstance().getId()))) {
|
||||||
addCounters(CounterType.M1M1.createInstance(actualDamage), game);
|
if (markDamage) {
|
||||||
|
// mark damage only
|
||||||
|
markDamage(CounterType.M1M1.createInstance(actualDamage));
|
||||||
|
} else {
|
||||||
|
// deal damage immediately
|
||||||
|
addCounters(CounterType.M1M1.createInstance(actualDamage), game);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.damage += actualDamage;
|
this.damage += actualDamage;
|
||||||
}
|
}
|
||||||
|
@ -580,6 +616,13 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void markDamage(Counter counter) {
|
||||||
|
if (markedDamage == null) {
|
||||||
|
markedDamage = new ArrayList<Counter>();
|
||||||
|
}
|
||||||
|
markedDamage.add(counter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void entersBattlefield(UUID sourceId, Game game) {
|
public void entersBattlefield(UUID sourceId, Game game) {
|
||||||
controlledFromStartOfTurn = false;
|
controlledFromStartOfTurn = false;
|
||||||
|
|
|
@ -68,11 +68,19 @@ public class CombatDamageStep extends Step<CombatDamageStep> {
|
||||||
public void beginStep(Game game, UUID activePlayerId) {
|
public void beginStep(Game game, UUID activePlayerId) {
|
||||||
super.beginStep(game, activePlayerId);
|
super.beginStep(game, activePlayerId);
|
||||||
for (CombatGroup group: game.getCombat().getGroups()) {
|
for (CombatGroup group: game.getCombat().getGroups()) {
|
||||||
group.assignDamage(first, game);
|
group.assignDamageToBlockers(first, game);
|
||||||
}
|
}
|
||||||
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
|
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
|
||||||
group.assignDamageToAttackers(first, game);
|
group.assignDamageToAttackers(first, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (CombatGroup group: game.getCombat().getGroups()) {
|
||||||
|
group.applyDamage(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
|
||||||
|
group.applyDamage(game);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getFirst() {
|
public boolean getFirst() {
|
||||||
|
|
Loading…
Reference in a new issue