mirror of
https://github.com/correl/mage.git
synced 2024-11-15 19:19:33 +00:00
Removed redundant combat code for handling block effect of Odric Master Tactician.
This commit is contained in:
parent
19679c9f6e
commit
bd77e476ee
2 changed files with 134 additions and 135 deletions
|
@ -142,28 +142,12 @@ class OdricMasterTacticianEffect extends ReplacementEffectImpl<OdricMasterTactic
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player blockController = game.getPlayer(source.getControllerId());
|
||||||
//20101001 - 509.1c
|
if (blockController != null) {
|
||||||
game.getCombat().checkBlockRequirementsBefore(player, game);
|
game.getCombat().selectBlockers(blockController, game);
|
||||||
for (UUID defenderId : game.getCombat().getPlayerDefenders(game)) {
|
|
||||||
boolean choose = true;
|
|
||||||
while (choose) {
|
|
||||||
game.getPlayer(source.getControllerId()).selectBlockers(game, defenderId);
|
|
||||||
if (game.isPaused() || game.isGameOver()) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!game.getCombat().checkBlockRestrictions(game.getPlayer(defenderId), game)) {
|
return false;
|
||||||
// only human player can decide to do the block in another way
|
|
||||||
if (player.isHuman()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
choose = !game.getCombat().checkBlockRequirementsAfter(game.getPlayer(defenderId), player, game);
|
|
||||||
}
|
|
||||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,31 +1,30 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
* authors and should not be interpreted as representing official policies, either expressed
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.game.combat;
|
package mage.game.combat;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -57,7 +56,6 @@ import mage.util.CardUtil;
|
||||||
import mage.util.Copyable;
|
import mage.util.Copyable;
|
||||||
import mage.util.trace.TraceUtil;
|
import mage.util.trace.TraceUtil;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
|
@ -81,7 +79,6 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
private final Map<UUID, Set<UUID>> creaturesForcedToAttack = new HashMap<UUID, Set<UUID>>();
|
private final Map<UUID, Set<UUID>> creaturesForcedToAttack = new HashMap<UUID, Set<UUID>>();
|
||||||
private int maxAttackers = Integer.MIN_VALUE;
|
private int maxAttackers = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
|
||||||
public Combat() {
|
public Combat() {
|
||||||
this.useToughnessForDamage = false;
|
this.useToughnessForDamage = false;
|
||||||
}
|
}
|
||||||
|
@ -163,8 +160,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an additional attacker to the combat (e.g. token of Geist of Saint Traft)
|
* Add an additional attacker to the combat (e.g. token of Geist of Saint
|
||||||
* This method doesn't trigger ATTACKER_DECLARED event (as intended).
|
* Traft) This method doesn't trigger ATTACKER_DECLARED event (as intended).
|
||||||
*
|
*
|
||||||
* @param creatureId - creature that shall be added to the combat
|
* @param creatureId - creature that shall be added to the combat
|
||||||
* @param game
|
* @param game
|
||||||
|
@ -175,8 +172,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
if (defenders.size() == 1) {
|
if (defenders.size() == 1) {
|
||||||
declareAttacker(creatureId, defenders.iterator().next(), game);
|
declareAttacker(creatureId, defenders.iterator().next(), game);
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
TargetDefender target = new TargetDefender(defenders, creatureId);
|
TargetDefender target = new TargetDefender(defenders, creatureId);
|
||||||
target.setRequired(true);
|
target.setRequired(true);
|
||||||
player.chooseTarget(Outcome.Damage, target, null, game);
|
player.chooseTarget(Outcome.Damage, target, null, game);
|
||||||
|
@ -204,8 +200,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
|
|
||||||
public void resumeSelectAttackers(Game game) {
|
public void resumeSelectAttackers(Game game) {
|
||||||
Player player = game.getPlayer(attackerId);
|
Player player = game.getPlayer(attackerId);
|
||||||
for (CombatGroup group: groups) {
|
for (CombatGroup group : groups) {
|
||||||
for (UUID attacker: group.getAttackers()) {
|
for (UUID attacker : group.getAttackers()) {
|
||||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ATTACKER_DECLARED, group.defenderId, attacker, attackerId));
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ATTACKER_DECLARED, group.defenderId, attacker, attackerId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,14 +213,14 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
//20101001 - 508.1d
|
//20101001 - 508.1d
|
||||||
for (Permanent creature : player.getAvailableAttackers(game)) {
|
for (Permanent creature : player.getAvailableAttackers(game)) {
|
||||||
boolean mustAttack = false;
|
boolean mustAttack = false;
|
||||||
Set <UUID> defendersForcedToAttack = new HashSet<UUID>();
|
Set<UUID> defendersForcedToAttack = new HashSet<UUID>();
|
||||||
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||||
RequirementEffect effect = (RequirementEffect)entry.getKey();
|
RequirementEffect effect = (RequirementEffect) entry.getKey();
|
||||||
if (effect.mustAttack(game)) {
|
if (effect.mustAttack(game)) {
|
||||||
mustAttack = true;
|
mustAttack = true;
|
||||||
for (Ability ability: (HashSet<Ability>)entry.getValue()) {
|
for (Ability ability : (HashSet<Ability>) entry.getValue()) {
|
||||||
UUID defenderId = effect.mustAttackDefender(ability, game);
|
UUID defenderId = effect.mustAttackDefender(ability, game);
|
||||||
if(defenderId != null) {
|
if (defenderId != null) {
|
||||||
defendersForcedToAttack.add(defenderId);
|
defendersForcedToAttack.add(defenderId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -232,7 +228,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mustAttack) {
|
if (mustAttack) {
|
||||||
creaturesForcedToAttack.put(creature.getId(),defendersForcedToAttack);
|
creaturesForcedToAttack.put(creature.getId(), defendersForcedToAttack);
|
||||||
if (defendersForcedToAttack.isEmpty()) {
|
if (defendersForcedToAttack.isEmpty()) {
|
||||||
if (defenders.size() == 1) {
|
if (defenders.size() == 1) {
|
||||||
player.declareAttacker(creature.getId(), defenders.iterator().next(), game);
|
player.declareAttacker(creature.getId(), defenders.iterator().next(), game);
|
||||||
|
@ -253,16 +249,16 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
|
|
||||||
protected void checkAttackRestrictions(Player player, Game game) {
|
protected void checkAttackRestrictions(Player player, Game game) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (CombatGroup group: groups) {
|
for (CombatGroup group : groups) {
|
||||||
count += group.getAttackers().size();
|
count += group.getAttackers().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
List<UUID> tobeRemoved = new ArrayList<UUID>();
|
List<UUID> tobeRemoved = new ArrayList<UUID>();
|
||||||
for (CombatGroup group: groups) {
|
for (CombatGroup group : groups) {
|
||||||
for (UUID attackingCreatureId: group.getAttackers()) {
|
for (UUID attackingCreatureId : group.getAttackers()) {
|
||||||
Permanent attacker = game.getPermanent(attackingCreatureId);
|
Permanent attacker = game.getPermanent(attackingCreatureId);
|
||||||
if (count >1 && attacker != null && attacker.getAbilities().containsKey(CanAttackOnlyAloneAbility.getInstance().getId())) {
|
if (count > 1 && attacker != null && attacker.getAbilities().containsKey(CanAttackOnlyAloneAbility.getInstance().getId())) {
|
||||||
game.informPlayers(attacker.getName() + " can only attack alone. Removing it from combat.");
|
game.informPlayers(attacker.getName() + " can only attack alone. Removing it from combat.");
|
||||||
tobeRemoved.add(attackingCreatureId);
|
tobeRemoved.add(attackingCreatureId);
|
||||||
count--;
|
count--;
|
||||||
|
@ -276,8 +272,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
|
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
List<UUID> tobeRemoved = new ArrayList<UUID>();
|
List<UUID> tobeRemoved = new ArrayList<UUID>();
|
||||||
for (CombatGroup group: groups) {
|
for (CombatGroup group : groups) {
|
||||||
for (UUID attackingCreatureId: group.getAttackers()) {
|
for (UUID attackingCreatureId : group.getAttackers()) {
|
||||||
Permanent attacker = game.getPermanent(attackingCreatureId);
|
Permanent attacker = game.getPermanent(attackingCreatureId);
|
||||||
if (attacker != null && attacker.getAbilities().containsKey(CantAttackAloneAbility.getInstance().getId())) {
|
if (attacker != null && attacker.getAbilities().containsKey(CantAttackAloneAbility.getInstance().getId())) {
|
||||||
game.informPlayers(attacker.getName() + " can't attack alone. Removing it from combat.");
|
game.informPlayers(attacker.getName() + " can't attack alone. Removing it from combat.");
|
||||||
|
@ -295,40 +291,63 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
|
|
||||||
public void selectBlockers(Game game) {
|
public void selectBlockers(Game game) {
|
||||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, attackerId, attackerId))) {
|
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, attackerId, attackerId))) {
|
||||||
|
game.getCombat().selectBlockers(null, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// !! Attention: Changes to this block must be also done in card "OdricMaster Tactician".
|
/**
|
||||||
Player player = game.getPlayer(attackerId);
|
* Handle the blocker selection process
|
||||||
|
*
|
||||||
|
* @param blockController player that controlls how to block, if null the defender is the controller
|
||||||
|
* @param game
|
||||||
|
*/
|
||||||
|
public void selectBlockers(Player blockController, Game game) {
|
||||||
|
Player attacker = game.getPlayer(attackerId);
|
||||||
//20101001 - 509.1c
|
//20101001 - 509.1c
|
||||||
checkBlockRequirementsBefore(player, game);
|
this.checkBlockRequirementsBefore(attacker, game);
|
||||||
for (UUID defenderId : getPlayerDefenders(game)) {
|
for (UUID defenderId : getPlayerDefenders(game)) {
|
||||||
boolean choose = true;
|
|
||||||
Player defender = game.getPlayer(defenderId);
|
Player defender = game.getPlayer(defenderId);
|
||||||
|
if (defender != null) {
|
||||||
|
boolean choose = true;
|
||||||
|
if (blockController == null) {
|
||||||
|
blockController = defender;
|
||||||
|
}
|
||||||
while (choose) {
|
while (choose) {
|
||||||
game.getPlayer(defenderId).selectBlockers(game, defenderId);
|
blockController.selectBlockers(game, defenderId);
|
||||||
if (game.isPaused() || game.isGameOver()) {
|
if (game.isPaused() || game.isGameOver()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!checkBlockRestrictions(game.getPlayer(defenderId), game)) {
|
if (!this.checkBlockRestrictions(defender, game)) {
|
||||||
// only human player can decide to do the block in another way
|
if (blockController.isHuman()) { // only human player can decide to do the block in another way
|
||||||
if (defender.isHuman()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
choose = !this.checkBlockRequirementsAfter(defender, blockController, game);
|
||||||
choose = !checkBlockRequirementsAfter(defender, defender, game);
|
|
||||||
}
|
}
|
||||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId));
|
||||||
|
|
||||||
// add info about attacker blocked by blocker to the game log
|
// add info about attacker blocked by blocker to the game log
|
||||||
|
this.logBlockerInfo(defender, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tool to catch the bug about flyers blocked by non flyers or intimidate blocked by creatures with other colors
|
||||||
|
TraceUtil.traceCombatIfNeeded(game, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add info about attacker blocked by blocker to the game log
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void logBlockerInfo(Player defender, Game game) {
|
||||||
boolean shownDefendingPlayer = false;
|
boolean shownDefendingPlayer = false;
|
||||||
for (CombatGroup group :this.getGroups()) {
|
for (CombatGroup group : this.getGroups()) {
|
||||||
if (group.defendingPlayerId.equals(defenderId)) {
|
if (group.defendingPlayerId.equals(defender.getId())) {
|
||||||
if (!shownDefendingPlayer && defender != null) {
|
if (!shownDefendingPlayer) {
|
||||||
game.informPlayers(new StringBuilder("Attacked player: ").append(defender.getName()).toString());
|
game.informPlayers(new StringBuilder("Attacked player: ").append(defender.getName()).toString());
|
||||||
shownDefendingPlayer = true;
|
shownDefendingPlayer = true;
|
||||||
}
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for(UUID attackingCreatureId : group.getAttackers()) {
|
for (UUID attackingCreatureId : group.getAttackers()) {
|
||||||
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
||||||
if (attackingCreature != null) {
|
if (attackingCreature != null) {
|
||||||
sb.append(attackingCreature.getName()).append(" (");
|
sb.append(attackingCreature.getName()).append(" (");
|
||||||
|
@ -343,7 +362,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
if (group.getBlockers().size() > 0) {
|
if (group.getBlockers().size() > 0) {
|
||||||
sb.append("blocked by ");
|
sb.append("blocked by ");
|
||||||
for(UUID blockingCreatureId : group.getBlockers()) {
|
for (UUID blockingCreatureId : group.getBlockers()) {
|
||||||
Permanent blockingCreature = game.getPermanent(blockingCreatureId);
|
Permanent blockingCreature = game.getPermanent(blockingCreatureId);
|
||||||
if (blockingCreature != null) {
|
if (blockingCreature != null) {
|
||||||
sb.append(blockingCreature.getName()).append(" (");
|
sb.append(blockingCreature.getName()).append(" (");
|
||||||
|
@ -351,20 +370,17 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else{
|
} else {
|
||||||
sb.append("unblocked");
|
sb.append("unblocked");
|
||||||
}
|
}
|
||||||
game.informPlayers(sb.toString());
|
game.informPlayers(sb.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
TraceUtil.traceCombatIfNeeded(game, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the block restrictions
|
* Check the block restrictions
|
||||||
|
*
|
||||||
* @param player
|
* @param player
|
||||||
* @param game
|
* @param game
|
||||||
* @return false - if block restrictions were not complied
|
* @return false - if block restrictions were not complied
|
||||||
|
@ -372,7 +388,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
public boolean checkBlockRestrictions(Player player, Game game) {
|
public boolean checkBlockRestrictions(Player player, Game game) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
boolean blockWasLegal = true;
|
boolean blockWasLegal = true;
|
||||||
for (CombatGroup group: groups) {
|
for (CombatGroup group : groups) {
|
||||||
count += group.getBlockers().size();
|
count += group.getBlockers().size();
|
||||||
}
|
}
|
||||||
for (CombatGroup group : groups) {
|
for (CombatGroup group : groups) {
|
||||||
|
@ -412,9 +428,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
for (Permanent creature : game.getBattlefield().getActivePermanents(filterBlockers, player.getId(), game)) {
|
for (Permanent creature : game.getBattlefield().getActivePermanents(filterBlockers, player.getId(), game)) {
|
||||||
if (game.getOpponents(attackerId).contains(creature.getControllerId())) {
|
if (game.getOpponents(attackerId).contains(creature.getControllerId())) {
|
||||||
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||||
RequirementEffect effect = (RequirementEffect)entry.getKey();
|
RequirementEffect effect = (RequirementEffect) entry.getKey();
|
||||||
if (effect.mustBlock(game)) {
|
if (effect.mustBlock(game)) {
|
||||||
for (Ability ability: (HashSet<Ability>)entry.getValue()) {
|
for (Ability ability : (HashSet<Ability>) entry.getValue()) {
|
||||||
UUID attackId = effect.mustBlockAttacker(ability, game);
|
UUID attackId = effect.mustBlockAttacker(ability, game);
|
||||||
Player defender = game.getPlayer(creature.getControllerId());
|
Player defender = game.getPlayer(creature.getControllerId());
|
||||||
if (attackId != null && defender != null) {
|
if (attackId != null && defender != null) {
|
||||||
|
@ -451,9 +467,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
if (creature.getBlocking() > 0) {
|
if (creature.getBlocking() > 0) {
|
||||||
// get all requirement effects that apply to the creature (ce.g. is able to block attacker)
|
// get all requirement effects that apply to the creature (ce.g. is able to block attacker)
|
||||||
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||||
RequirementEffect effect = (RequirementEffect)entry.getKey();
|
RequirementEffect effect = (RequirementEffect) entry.getKey();
|
||||||
// get possible mustBeBlockedByAtLeastOne blocker
|
// get possible mustBeBlockedByAtLeastOne blocker
|
||||||
for (Ability ability: (HashSet<Ability>)entry.getValue()) {
|
for (Ability ability : (HashSet<Ability>) entry.getValue()) {
|
||||||
UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game);
|
UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game);
|
||||||
if (toBeBlockedCreature != null) {
|
if (toBeBlockedCreature != null) {
|
||||||
Set<UUID> potentialBlockers;
|
Set<UUID> potentialBlockers;
|
||||||
|
@ -473,9 +489,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
if (creature.getBlocking() == 0) {
|
if (creature.getBlocking() == 0) {
|
||||||
// get all requirement effects that apply to the creature
|
// get all requirement effects that apply to the creature
|
||||||
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
|
||||||
RequirementEffect effect = (RequirementEffect)entry.getKey();
|
RequirementEffect effect = (RequirementEffect) entry.getKey();
|
||||||
// get possible mustBeBlockedByAtLeastOne blocker
|
// get possible mustBeBlockedByAtLeastOne blocker
|
||||||
for (Ability ability: (HashSet<Ability>)entry.getValue()) {
|
for (Ability ability : (HashSet<Ability>) entry.getValue()) {
|
||||||
UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game);
|
UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game);
|
||||||
if (toBeBlockedCreature != null) {
|
if (toBeBlockedCreature != null) {
|
||||||
Set<UUID> potentialBlockers;
|
Set<UUID> potentialBlockers;
|
||||||
|
@ -499,7 +515,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// is so inform human player or set block for AI player
|
// if so inform human player or set block for AI player
|
||||||
if (mayBlock) {
|
if (mayBlock) {
|
||||||
if (controller.isHuman()) {
|
if (controller.isHuman()) {
|
||||||
game.informPlayer(controller, "Creature should block this turn: " + creature.getName());
|
game.informPlayer(controller, "Creature should block this turn: " + creature.getName());
|
||||||
|
@ -526,7 +542,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check attacking creature mustBeBlockedByAtLeastOne
|
// check attacking creature mustBeBlockedByAtLeastOne
|
||||||
for (UUID toBeBlockedCreatureId: mustBeBlockedByAtLeastOne.keySet()) {
|
for (UUID toBeBlockedCreatureId : mustBeBlockedByAtLeastOne.keySet()) {
|
||||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||||
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
|
if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(toBeBlockedCreatureId)) {
|
||||||
// creature is not blocked but has possible blockers
|
// creature is not blocked but has possible blockers
|
||||||
|
@ -592,7 +608,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
// check if creatures are forced to block but do not block at all or block creatures they are not forced to block
|
// check if creatures are forced to block but do not block at all or block creatures they are not forced to block
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (Map.Entry<UUID, Set<UUID>> entry :creaturesForcedToBlockAttackers.entrySet()) {
|
for (Map.Entry<UUID, Set<UUID>> entry : creaturesForcedToBlockAttackers.entrySet()) {
|
||||||
boolean blockIsValid;
|
boolean blockIsValid;
|
||||||
Permanent creatureForcedToBlock = game.getPermanent(entry.getKey());
|
Permanent creatureForcedToBlock = game.getPermanent(entry.getKey());
|
||||||
if (creatureForcedToBlock == null) {
|
if (creatureForcedToBlock == null) {
|
||||||
|
@ -607,7 +623,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
CombatGroups:
|
CombatGroups:
|
||||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||||
if (combatGroup.getBlockers().contains(creatureForcedToBlock.getId())) {
|
if (combatGroup.getBlockers().contains(creatureForcedToBlock.getId())) {
|
||||||
for (UUID forcingAttackerId :combatGroup.getAttackers()) {
|
for (UUID forcingAttackerId : combatGroup.getAttackers()) {
|
||||||
if (entry.getValue().contains(forcingAttackerId)) {
|
if (entry.getValue().contains(forcingAttackerId)) {
|
||||||
// the creature is blocking a forcing attacker, so the block is ok
|
// the creature is blocking a forcing attacker, so the block is ok
|
||||||
blockIsValid = true;
|
blockIsValid = true;
|
||||||
|
@ -706,7 +722,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId(): defenderId);
|
CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId);
|
||||||
newGroup.attackers.add(attackerId);
|
newGroup.attackers.add(attackerId);
|
||||||
Permanent attacker = game.getPermanent(attackerId);
|
Permanent attacker = game.getPermanent(attackerId);
|
||||||
if (!attacker.getAbilities().containsKey(VigilanceAbility.getInstance().getId())) {
|
if (!attacker.getAbilities().containsKey(VigilanceAbility.getInstance().getId())) {
|
||||||
|
@ -969,7 +985,6 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
return maxAttackers;
|
return maxAttackers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Combat copy() {
|
public Combat copy() {
|
||||||
return new Combat(this);
|
return new Combat(this);
|
||||||
|
|
Loading…
Reference in a new issue