mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
* Fixed a bug that caused creatures forced to attack could prevent to attack by deselecting the forced creature or be able to attack another defender by using the Attack All button.
This commit is contained in:
parent
7f8854aa0f
commit
0176478441
4 changed files with 33 additions and 25 deletions
|
@ -905,6 +905,15 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
attackedDefender, attacker.getId(), attacker.getControllerId()), game)) {
|
attackedDefender, attacker.getId(), attacker.getControllerId()), game)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// if attacker needs a specific defender to attack so select that one instead
|
||||||
|
if (game.getCombat().getCreaturesForcedToAttack().containsKey(attacker.getId())) {
|
||||||
|
Set<UUID> possibleDefenders = game.getCombat().getCreaturesForcedToAttack().get(attacker.getId());
|
||||||
|
if (!possibleDefenders.isEmpty() && !possibleDefenders.contains(attackedDefender)) {
|
||||||
|
declareAttacker(attacker.getId(), possibleDefenders.iterator().next(), game, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// attack selected default defender
|
||||||
declareAttacker(attacker.getId(), attackedDefender, game, false);
|
declareAttacker(attacker.getId(), attackedDefender, game, false);
|
||||||
}
|
}
|
||||||
} else if (response.getBoolean() != null) {
|
} else if (response.getBoolean() != null) {
|
||||||
|
@ -926,14 +935,18 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
} else {
|
} else {
|
||||||
Permanent creature = game.getPermanent(creatureId);
|
Permanent creature = game.getPermanent(creatureId);
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
sb.append(creature.getName()).append(" ");
|
sb.append(creature.getIdName()).append(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (game.getCombat().getMaxAttackers() > forcedAttackers) {
|
if (game.getCombat().getMaxAttackers() > forcedAttackers) {
|
||||||
game.informPlayer(this, sb.insert(0, " more attacker(s) that are forced to attack.\nCreatures forced to attack: ")
|
int requireToAttack = Math.min(game.getCombat().getMaxAttackers() - forcedAttackers, game.getCombat().getCreaturesForcedToAttack().size() - forcedAttackers);
|
||||||
.insert(0, Math.min(game.getCombat().getMaxAttackers() - forcedAttackers, game.getCombat().getCreaturesForcedToAttack().size() - forcedAttackers))
|
String message = (requireToAttack == 1 ? " more attacker that is " : " more attackers that are ")
|
||||||
|
+ "forced to attack.\nCreature"
|
||||||
|
+ (requireToAttack == 1 ? "" : "s") + " forced to attack: ";
|
||||||
|
game.informPlayer(this, sb.insert(0, message)
|
||||||
|
.insert(0, requireToAttack)
|
||||||
.insert(0, "You have to attack with ").toString());
|
.insert(0, "You have to attack with ").toString());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -989,7 +1002,7 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
possibleDefender = defenders;
|
possibleDefender = defenders;
|
||||||
}
|
}
|
||||||
if (possibleDefender.size() == 1) {
|
if (possibleDefender.size() == 1) {
|
||||||
declareAttacker(attackerId, defenders.iterator().next(), game, true);
|
declareAttacker(attackerId, possibleDefender.iterator().next(), game, true);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
TargetDefender target = new TargetDefender(possibleDefender, attackerId);
|
TargetDefender target = new TargetDefender(possibleDefender, attackerId);
|
||||||
|
|
|
@ -32,10 +32,8 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.LoyaltyAbility;
|
import mage.abilities.LoyaltyAbility;
|
||||||
import mage.abilities.common.EntersBattlefieldAbility;
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
|
||||||
import mage.abilities.dynamicvalue.common.CountersCount;
|
import mage.abilities.dynamicvalue.common.CountersCount;
|
||||||
import mage.abilities.dynamicvalue.common.PermanentsTargetOpponentControlsCount;
|
import mage.abilities.dynamicvalue.common.PermanentsTargetOpponentControlsCount;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.PreventAllDamageToSourceEffect;
|
import mage.abilities.effects.common.PreventAllDamageToSourceEffect;
|
||||||
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
|
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
|
||||||
|
|
|
@ -62,27 +62,27 @@ import mage.target.common.TargetCreaturePermanent;
|
||||||
public class GideonBattleForged extends CardImpl {
|
public class GideonBattleForged extends CardImpl {
|
||||||
|
|
||||||
private final static FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
private final static FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new ControllerPredicate(TargetController.OPPONENT));
|
filter.add(new ControllerPredicate(TargetController.OPPONENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GideonBattleForged(UUID ownerId) {
|
public GideonBattleForged(UUID ownerId) {
|
||||||
super(ownerId, 23, "Gideon, Battle-Forged", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "");
|
super(ownerId, 23, "Gideon, Battle-Forged", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "");
|
||||||
this.expansionSetCode = "ORI";
|
this.expansionSetCode = "ORI";
|
||||||
this.subtype.add("Gideon");
|
this.subtype.add("Gideon");
|
||||||
|
|
||||||
this.color.setWhite(true);
|
this.color.setWhite(true);
|
||||||
|
|
||||||
this.nightCard = true;
|
this.nightCard = true;
|
||||||
this.canTransform = true;
|
this.canTransform = true;
|
||||||
|
|
||||||
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(3)), false));
|
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(3)), false));
|
||||||
|
|
||||||
// +2: Up to one target creature an opponent controls attacks Gideon, Battle-Forged during its controller's next turn if able.
|
// +2: Up to one target creature an opponent controls attacks Gideon, Battle-Forged during its controller's next turn if able.
|
||||||
LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new GideonBattleForgedAttacksIfAbleTargetEffect(Duration.Custom), 2);
|
LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new GideonBattleForgedAttacksIfAbleTargetEffect(Duration.Custom), 2);
|
||||||
loyaltyAbility.addTarget(new TargetCreaturePermanent(0,1,filter, false));
|
loyaltyAbility.addTarget(new TargetCreaturePermanent(0, 1, filter, false));
|
||||||
this.addAbility(loyaltyAbility);
|
this.addAbility(loyaltyAbility);
|
||||||
|
|
||||||
// +1: Until your next turn, target creature gains indestructible. Untap that creature.
|
// +1: Until your next turn, target creature gains indestructible. Untap that creature.
|
||||||
Effect effect = new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.UntilYourNextTurn);
|
Effect effect = new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.UntilYourNextTurn);
|
||||||
|
@ -92,14 +92,14 @@ public class GideonBattleForged extends CardImpl {
|
||||||
effect = new UntapTargetEffect();
|
effect = new UntapTargetEffect();
|
||||||
effect.setText("Untap that creature");
|
effect.setText("Untap that creature");
|
||||||
loyaltyAbility.addEffect(effect);
|
loyaltyAbility.addEffect(effect);
|
||||||
this.addAbility(loyaltyAbility);
|
this.addAbility(loyaltyAbility);
|
||||||
|
|
||||||
// 0: Until end of turn, Gideon, Battle-Forged becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn.
|
// 0: Until end of turn, Gideon, Battle-Forged becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn.
|
||||||
LoyaltyAbility ability3 = new LoyaltyAbility(new BecomesCreatureSourceEffect(new GideonBattleForgedToken(), "planeswalker", Duration.EndOfTurn), 0);
|
LoyaltyAbility ability3 = new LoyaltyAbility(new BecomesCreatureSourceEffect(new GideonBattleForgedToken(), "planeswalker", Duration.EndOfTurn), 0);
|
||||||
effect = new PreventAllDamageToSourceEffect(Duration.EndOfTurn);
|
effect = new PreventAllDamageToSourceEffect(Duration.EndOfTurn);
|
||||||
effect.setText("Prevent all damage that would be dealt to him this turn");
|
effect.setText("Prevent all damage that would be dealt to him this turn");
|
||||||
ability3.addEffect(effect);
|
ability3.addEffect(effect);
|
||||||
this.addAbility(ability3);
|
this.addAbility(ability3);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect {
|
||||||
|
|
||||||
int nextTurnTargetController = 0;
|
int nextTurnTargetController = 0;
|
||||||
protected MageObjectReference targetPermanentReference;
|
protected MageObjectReference targetPermanentReference;
|
||||||
|
|
||||||
public GideonBattleForgedAttacksIfAbleTargetEffect(Duration duration) {
|
public GideonBattleForgedAttacksIfAbleTargetEffect(Duration duration) {
|
||||||
super(duration);
|
super(duration);
|
||||||
staticText = "Up to one target creature an opponent controls attacks {this} during its controller's next turn if able";
|
staticText = "Up to one target creature an opponent controls attacks {this} during its controller's next turn if able";
|
||||||
|
@ -147,7 +147,7 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect {
|
||||||
public GideonBattleForgedAttacksIfAbleTargetEffect copy() {
|
public GideonBattleForgedAttacksIfAbleTargetEffect copy() {
|
||||||
return new GideonBattleForgedAttacksIfAbleTargetEffect(this);
|
return new GideonBattleForgedAttacksIfAbleTargetEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInactive(Ability source, Game game) {
|
public boolean isInactive(Ability source, Game game) {
|
||||||
if (targetPermanentReference == null) {
|
if (targetPermanentReference == null) {
|
||||||
|
@ -160,10 +160,7 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect {
|
||||||
if (nextTurnTargetController == 0 && startingTurn != game.getTurnNum() && game.getActivePlayerId().equals(targetPermanent.getControllerId())) {
|
if (nextTurnTargetController == 0 && startingTurn != game.getTurnNum() && game.getActivePlayerId().equals(targetPermanent.getControllerId())) {
|
||||||
nextTurnTargetController = game.getTurnNum();
|
nextTurnTargetController = game.getTurnNum();
|
||||||
}
|
}
|
||||||
if (game.getPhase().getType() == TurnPhase.END && nextTurnTargetController > 0 && game.getTurnNum() > nextTurnTargetController) {
|
return game.getPhase().getType() == TurnPhase.END && nextTurnTargetController > 0 && game.getTurnNum() > nextTurnTargetController;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -175,7 +172,7 @@ class GideonBattleForgedAttacksIfAbleTargetEffect extends RequirementEffect {
|
||||||
targetPermanentReference = new MageObjectReference(getTargetPointer().getFirst(game, source), game);
|
targetPermanentReference = new MageObjectReference(getTargetPointer().getFirst(game, source), game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||||
if (permanent.getId().equals(getTargetPointer().getFirst(game, source))) {
|
if (permanent.getId().equals(getTargetPointer().getFirst(game, source))) {
|
||||||
|
|
|
@ -294,9 +294,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
||||||
}
|
}
|
||||||
// force attack only if a defender can be attacked without paying a cost
|
// force attack only if a defender can be attacked without paying a cost
|
||||||
if (!defendersCostlessAttackable.isEmpty()) {
|
if (!defendersCostlessAttackable.isEmpty()) {
|
||||||
|
creaturesForcedToAttack.put(creature.getId(), defendersForcedToAttack);
|
||||||
// No need to attack a special defender
|
// No need to attack a special defender
|
||||||
if (defendersForcedToAttack.isEmpty()) {
|
if (defendersForcedToAttack.isEmpty()) {
|
||||||
creaturesForcedToAttack.put(creature.getId(), defendersForcedToAttack);
|
|
||||||
if (defendersForcedToAttack.isEmpty()) {
|
if (defendersForcedToAttack.isEmpty()) {
|
||||||
if (defendersCostlessAttackable.size() == 1) {
|
if (defendersCostlessAttackable.size() == 1) {
|
||||||
player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false);
|
player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false);
|
||||||
|
|
Loading…
Reference in a new issue