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());
|
||||
}
|
||||
|
||||
public void assignDamage(boolean first, Game game) {
|
||||
public void assignDamageToBlockers(boolean first, Game game) {
|
||||
if (attackers.size() > 0 && (!first || hasFirstOrDoubleStrike(game))) {
|
||||
if (blockers.size() == 0) {
|
||||
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
|
||||
*
|
||||
|
@ -218,25 +233,25 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
if (hasTrample(attacker)) {
|
||||
int lethalDamage = blocker.getToughness().getValue() - blocker.getDamage();
|
||||
if (lethalDamage >= damage) {
|
||||
blocker.damage(damage, attacker.getId(), game, true, true);
|
||||
blocker.markDamage(damage, attacker.getId(), game, true, true);
|
||||
}
|
||||
else {
|
||||
Player player = game.getPlayer(attacker.getControllerId());
|
||||
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;
|
||||
if (damage > 0)
|
||||
defenderDamage(attacker, damage, game);
|
||||
}
|
||||
}
|
||||
else {
|
||||
blocker.damage(damage, attacker.getId(), game, true, true);
|
||||
blocker.markDamage(damage, attacker.getId(), game, true, true);
|
||||
}
|
||||
}
|
||||
if (canDamage(blocker, first)) {
|
||||
if (blocker.getBlocking() == 1) { // blocking several creatures handled separately
|
||||
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);
|
||||
if (canDamage(blocker, first)) {
|
||||
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
|
||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||
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 {
|
||||
for (UUID blockerId: blockerOrder) {
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
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 (canDamage(blocker, first)) {
|
||||
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()) {
|
||||
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) {
|
||||
Permanent defender = game.getPermanent(defenderId);
|
||||
if (defender != null) {
|
||||
defender.damage(amount, attacker.getId(), game, true, true);
|
||||
defender.markDamage(amount, attacker.getId(), game, true, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -75,6 +75,11 @@ public interface Permanent extends Card {
|
|||
public boolean hasSummoningSickness();
|
||||
public int getDamage();
|
||||
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 Counters getCounters();
|
||||
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.players.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
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> dealtDamageByThisTurn;
|
||||
protected UUID attachedTo;
|
||||
protected List<Counter> markedDamage;
|
||||
|
||||
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) {
|
||||
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.minBlockedBy = permanent.minBlockedBy;
|
||||
|
@ -505,12 +510,26 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
|||
|
||||
@Override
|
||||
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;
|
||||
if (damageAmount > 0 && canDamage(game.getObject(sourceId))) {
|
||||
if (cardType.contains(CardType.PLANESWALKER)) {
|
||||
damageDone = damagePlaneswalker(damageAmount, sourceId, game, preventable, combat);
|
||||
damageDone = damagePlaneswalker(damageAmount, sourceId, game, preventable, combat, markDamage);
|
||||
} else {
|
||||
damageDone = damageCreature(damageAmount, sourceId, game, preventable, combat);
|
||||
damageDone = damageCreature(damageAmount, sourceId, game, preventable, combat, markDamage);
|
||||
}
|
||||
if (damageDone > 0) {
|
||||
Permanent source = game.getPermanent(sourceId);
|
||||
|
@ -530,13 +549,31 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
|||
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
|
||||
public void removeAllDamage(Game game) {
|
||||
damage = 0;
|
||||
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);
|
||||
if (!game.replaceEvent(event)) {
|
||||
int actualDamage = event.getAmount();
|
||||
|
@ -553,23 +590,22 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
|||
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);
|
||||
if (!game.replaceEvent(event)) {
|
||||
int actualDamage = event.getAmount();
|
||||
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);
|
||||
MageObject source = game.getObject(sourceId);
|
||||
if (source != null && (source.getAbilities().containsKey(InfectAbility.getInstance().getId())
|
||||
|| source.getAbilities().containsKey(WitherAbility.getInstance().getId()))) {
|
||||
if (markDamage) {
|
||||
// mark damage only
|
||||
markDamage(CounterType.M1M1.createInstance(actualDamage));
|
||||
} else {
|
||||
// deal damage immediately
|
||||
addCounters(CounterType.M1M1.createInstance(actualDamage), game);
|
||||
}
|
||||
} else {
|
||||
this.damage += actualDamage;
|
||||
}
|
||||
|
@ -580,6 +616,13 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
|
|||
return 0;
|
||||
}
|
||||
|
||||
private void markDamage(Counter counter) {
|
||||
if (markedDamage == null) {
|
||||
markedDamage = new ArrayList<Counter>();
|
||||
}
|
||||
markedDamage.add(counter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entersBattlefield(UUID sourceId, Game game) {
|
||||
controlledFromStartOfTurn = false;
|
||||
|
|
|
@ -68,11 +68,19 @@ public class CombatDamageStep extends Step<CombatDamageStep> {
|
|||
public void beginStep(Game game, UUID activePlayerId) {
|
||||
super.beginStep(game, activePlayerId);
|
||||
for (CombatGroup group: game.getCombat().getGroups()) {
|
||||
group.assignDamage(first, game);
|
||||
group.assignDamageToBlockers(first, game);
|
||||
}
|
||||
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
|
||||
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() {
|
||||
|
|
Loading…
Reference in a new issue