mirror of
https://github.com/correl/mage.git
synced 2025-01-13 19:11:33 +00:00
Fixed undoing individual blocker declarations for multi-blockers
One more #4172 fix
This commit is contained in:
parent
56c615a66f
commit
8f9356533d
1 changed files with 193 additions and 6 deletions
|
@ -678,6 +678,82 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
potentialBlockers.add(creature.getId());
|
potentialBlockers.add(creature.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check the mustBlockAllAttackers requirement (Blaze of Glory) -------------------------------
|
||||||
|
if (effect.mustBlockAllAttackers(game)) {
|
||||||
|
Set<UUID> attackersToBlock = new HashSet<>();
|
||||||
|
// check that it can block at least one of the attackers
|
||||||
|
// and no restictions prevent this
|
||||||
|
boolean mayBlock = false;
|
||||||
|
for (UUID attackingCreatureId : getAttackers()) {
|
||||||
|
if (creature.canBlock(attackingCreatureId, game)) {
|
||||||
|
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
||||||
|
if (attackingCreature != null) {
|
||||||
|
// check if the attacker is already blocked by a max of blockers, so blocker can't block it also
|
||||||
|
if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers
|
||||||
|
int alreadyBlockingCreatures = 0;
|
||||||
|
for (CombatGroup group : getGroups()) {
|
||||||
|
if (group.getAttackers().contains(attackingCreatureId)) {
|
||||||
|
alreadyBlockingCreatures = group.getBlockers().size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
|
||||||
|
// Attacker can't be blocked by more blockers so check next attacker
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check restrictions of the creature to block that prevent it can be blocked
|
||||||
|
|
||||||
|
if (attackingCreature.getMinBlockedBy() > 1) {
|
||||||
|
// TODO: check if enough possible blockers are available, if true, mayBlock can be set to true
|
||||||
|
|
||||||
|
} else {
|
||||||
|
attackersToBlock.add(attackingCreatureId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//~ // remove creatures already blocked by affected creature
|
||||||
|
//~ for (CombatGroup group : getBlockingGroups()) {
|
||||||
|
//~ if (group.getAttackers().contains(attackingCreatureId)) {
|
||||||
|
//~ for (UUID attackingCreatureId : group.getAttackers()) {
|
||||||
|
//~ CombatGroup attackersGroup = findGroup(attackingCreatureId);
|
||||||
|
//~ if (attackersGroup != null) {
|
||||||
|
//~ if (attackersGroup.getBlockers().contains(creature.getId())) {
|
||||||
|
//~ attackersToBlock.remove(attackingCreatureId);
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
if (!attackersToBlock.isEmpty()) {
|
||||||
|
if (attackersToBlock.size() > creature.getBlocking()) {
|
||||||
|
mayBlock = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if so inform human player or set block for AI player
|
||||||
|
if (mayBlock) {
|
||||||
|
if (controller.isHuman()) {
|
||||||
|
if (!game.isSimulation()) {
|
||||||
|
game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Player defender = game.getPlayer(creature.getControllerId());
|
||||||
|
if (defender != null) {
|
||||||
|
for (UUID attackingCreatureId : getAttackers()) {
|
||||||
|
if (creature.canBlock(attackingCreatureId, game)) {
|
||||||
|
// ???
|
||||||
|
if (attackersToBlock.contains(attackingCreatureId)) {
|
||||||
|
//~ defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
|
||||||
|
addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,8 +777,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the mustBlockAny requirement ----------------------------------------
|
// check the mustBlockAny requirement ---------------------------------------- (and mustBlockAllAttackers for AI)
|
||||||
if (effect.mustBlockAny(game)) {
|
if (effect.mustBlockAny(game) || effect.mustBlockAllAttackers(game)) {
|
||||||
// check that it can block at least one of the attackers
|
// check that it can block at least one of the attackers
|
||||||
// and no restictions prevent this
|
// and no restictions prevent this
|
||||||
boolean mayBlock = false;
|
boolean mayBlock = false;
|
||||||
|
@ -740,15 +816,28 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
if (mayBlock) {
|
if (mayBlock) {
|
||||||
if (controller.isHuman()) {
|
if (controller.isHuman()) {
|
||||||
if (!game.isSimulation()) {
|
if (!game.isSimulation()) {
|
||||||
game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName());
|
if (!effect.mustBlockAllAttackers(game)) {
|
||||||
|
game.informPlayer(controller, "Creature should block this turn: " + creature.getIdName());
|
||||||
|
} else {
|
||||||
|
game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Player defender = game.getPlayer(creature.getControllerId());
|
Player defender = game.getPlayer(creature.getControllerId());
|
||||||
if (defender != null) {
|
if (defender != null) {
|
||||||
for (UUID attackingCreatureId : getAttackers()) {
|
for (UUID attackingCreatureId : getAttackers()) {
|
||||||
if (creature.canBlock(attackingCreatureId, game)) {
|
if (creature.canBlock(attackingCreatureId, game)) {
|
||||||
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
|
if (!effect.mustBlockAllAttackers(game)) {
|
||||||
break;
|
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// this might be buggy with additional restriction effects
|
||||||
|
if (creature.getBlocking() == 0) {
|
||||||
|
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
|
||||||
|
} else {
|
||||||
|
addBlockingGroup(creature.getId(), creature.getId(), defender.getId(), game);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -756,6 +845,82 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
// check the mustBlockAllAttackers requirement -------------------------------
|
||||||
|
if (effect.mustBlockAllAttackers(game)) {
|
||||||
|
Set<UUID> attackersToBlock = new HashSet<>();
|
||||||
|
// check that it can block at least one of the attackers
|
||||||
|
// and no restictions prevent this
|
||||||
|
boolean mayBlock = false;
|
||||||
|
for (UUID attackingCreatureId : getAttackers()) {
|
||||||
|
if (creature.canBlock(attackingCreatureId, game)) {
|
||||||
|
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
||||||
|
if (attackingCreature != null) {
|
||||||
|
// check if the attacker is already blocked by a max of blockers, so blocker can't block it also
|
||||||
|
if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers
|
||||||
|
int alreadyBlockingCreatures = 0;
|
||||||
|
for (CombatGroup group : getGroups()) {
|
||||||
|
if (group.getAttackers().contains(attackingCreatureId)) {
|
||||||
|
alreadyBlockingCreatures = group.getBlockers().size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
|
||||||
|
// Attacker can't be blocked by more blockers so check next attacker
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check restrictions of the creature to block that prevent it can be blocked
|
||||||
|
|
||||||
|
if (attackingCreature.getMinBlockedBy() > 1) {
|
||||||
|
// TODO: check if enough possible blockers are available, if true, mayBlock can be set to true
|
||||||
|
|
||||||
|
} else {
|
||||||
|
attackersToBlock.add(attackingCreatureId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!attackersToBlock.isEmpty()) {
|
||||||
|
//~ CombatGroup group = findGroupOfBlocker(creature.getId());
|
||||||
|
//~ if (group == null) {
|
||||||
|
//~ mayBlock = true;
|
||||||
|
//~ } else {
|
||||||
|
//~ for (UUID attackingCreatureId : attackersToBlock) {
|
||||||
|
//~ if (!group.getAttackers().contains(attackingCreatureId)) {
|
||||||
|
//~ mayBlock = true;
|
||||||
|
//~ break;
|
||||||
|
//~ }
|
||||||
|
//~ }
|
||||||
|
game.informPlayers(attackersToBlock.size() + " and " + creature.getBlocking());
|
||||||
|
if (attackersToBlock.size() > creature.getBlocking()) {
|
||||||
|
mayBlock = true;
|
||||||
|
}
|
||||||
|
//~ }
|
||||||
|
}
|
||||||
|
// if so inform human player or set block for AI player
|
||||||
|
if (mayBlock) {
|
||||||
|
if (controller.isHuman()) {
|
||||||
|
if (!game.isSimulation()) {
|
||||||
|
game.informPlayer(controller, "Creature should block all attackers if able this turn: " + creature.getIdName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Player defender = game.getPlayer(creature.getControllerId());
|
||||||
|
if (defender != null) {
|
||||||
|
for (UUID attackingCreatureId : getAttackers()) {
|
||||||
|
if (creature.canBlock(attackingCreatureId, game)) {
|
||||||
|
// ???
|
||||||
|
if (attackersToBlock.contains(attackingCreatureId)) {
|
||||||
|
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1180,6 +1345,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
//TODO: handle banding
|
//TODO: handle banding
|
||||||
blockingGroups.get(blockerId).attackers.add(attackerId);
|
blockingGroups.get(blockerId).attackers.add(attackerId);
|
||||||
}
|
}
|
||||||
|
// "blocker.setBlocking(blocker.getBlocking() + 1)" is handled by the attacking combat group
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,6 +1558,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBlockerGromGroup(UUID blockerId, CombatGroup groupToUnblock, Game game) {
|
public void removeBlockerGromGroup(UUID blockerId, CombatGroup groupToUnblock, Game game) {
|
||||||
|
// Manual player action for undoing one declared blocker (used for multi-blocker creatures)
|
||||||
Permanent creature = game.getPermanent(blockerId);
|
Permanent creature = game.getPermanent(blockerId);
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
for (CombatGroup group : groups) {
|
for (CombatGroup group : groups) {
|
||||||
|
@ -1404,7 +1571,26 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
if (creature.getBlocking() > 0) {
|
if (creature.getBlocking() > 0) {
|
||||||
creature.setBlocking(creature.getBlocking() - 1);
|
creature.setBlocking(creature.getBlocking() - 1);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException("Tryinging creature to unblock, but blocking number value of creature < 1");
|
throw new UnsupportedOperationException("Trying to unblock creature, but blocking number value of creature < 1");
|
||||||
|
}
|
||||||
|
boolean canRemove = false;
|
||||||
|
for (CombatGroup blockGroup : getBlockingGroups()) {
|
||||||
|
if (blockGroup.blockers.contains(blockerId)) {
|
||||||
|
for (UUID attackerId : group.getAttackers()) {
|
||||||
|
blockGroup.attackers.remove(attackerId);
|
||||||
|
blockGroup.attackerOrder.remove(attackerId);
|
||||||
|
}
|
||||||
|
if (creature.getBlocking() == 0) {
|
||||||
|
blockGroup.blockers.remove(blockerId);
|
||||||
|
blockGroup.attackerOrder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blockGroup.blockers.isEmpty()) {
|
||||||
|
canRemove = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canRemove) {
|
||||||
|
blockingGroups.remove(blockerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1412,6 +1598,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBlocker(UUID blockerId, Game game) {
|
public void removeBlocker(UUID blockerId, Game game) {
|
||||||
|
// Manual player action for undoing all declared blockers (used for single-blocker creatures and multi-blockers exceeding blocking limit)
|
||||||
for (CombatGroup group : groups) {
|
for (CombatGroup group : groups) {
|
||||||
if (group.blockers.contains(blockerId)) {
|
if (group.blockers.contains(blockerId)) {
|
||||||
group.blockers.remove(blockerId);
|
group.blockers.remove(blockerId);
|
||||||
|
|
Loading…
Reference in a new issue