[CMM] Implement Teyo, Geometric Tactician (#10736)

* [CMM] Implement Teyo, Geometric Tactician

* rework as a RestrictionEffect (common class with Mystic Barrier; Pramikon, Sky Rampart)

* add checkMayAttackDefender test

* more Pramikon tests
This commit is contained in:
Susucre 2023-08-13 01:02:23 +02:00 committed by GitHub
parent e49020e490
commit 07ee4661e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 598 additions and 182 deletions

View file

@ -0,0 +1,100 @@
package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.ChooseModeEffect;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.players.PlayerList;
import java.util.UUID;
/**
* @author TheElk801, Susucr
*/
public class PlayerCanOnlyAttackInDirectionRestrictionEffect extends RestrictionEffect {
public static final String ALLOW_ATTACKING_LEFT = "Allow attacking left";
public static final String ALLOW_ATTACKING_RIGHT = "Allow attacking right";
public PlayerCanOnlyAttackInDirectionRestrictionEffect(Duration duration, String directionText) {
super(duration, Outcome.Neutral);
staticText = duration + (duration.toString().isEmpty() ? "" : ", ")
+ "each player may attack only the nearest opponent "
+ "in " + directionText + " and planeswalkers controlled by that opponent";
}
private PlayerCanOnlyAttackInDirectionRestrictionEffect(PlayerCanOnlyAttackInDirectionRestrictionEffect effect) {
super(effect);
}
@Override
public PlayerCanOnlyAttackInDirectionRestrictionEffect copy() {
return new PlayerCanOnlyAttackInDirectionRestrictionEffect(this);
}
public static Effect choiceEffect() {
return new ChooseModeEffect(
"Choose a direction to allow attacking in.",
ALLOW_ATTACKING_LEFT, ALLOW_ATTACKING_RIGHT
).setText("choose left or right");
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return true;
}
@Override
public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game, boolean canUseChooseDialogs) {
if (defenderId == null) {
return true;
}
String allowedDirection = (String) game.getState().getValue(source.getSourceId() + "_modeChoice");
if (allowedDirection == null) {
return true; // If no choice was made, the ability has no effect.
}
Player playerAttacking = game.getPlayer(attacker.getControllerId());
if (playerAttacking == null) {
return true;
}
// The attacking player should be in range of the source's controller
if (!game.getState().getPlayersInRange(source.getControllerId(), game).contains(playerAttacking.getId())) {
return true;
}
Player playerDefending = game.getPlayer(defenderId);
if (playerDefending == null) {
Permanent planeswalker = game.getPermanent(defenderId);
if (planeswalker != null && planeswalker.getCardType(game).contains(CardType.PLANESWALKER)) {
playerDefending = game.getPlayer(planeswalker.getControllerId());
}
}
if (playerDefending == null) {
return false; // not a planeswalker, either a battle or not on battelfield/game anymore.
}
PlayerList playerList = game.getState().getPlayerList(playerAttacking.getId());
if (allowedDirection.equals(ALLOW_ATTACKING_LEFT)
&& !playerList.getNext().equals(playerDefending.getId())) {
// the defender is not the player to the left
return false;
}
if (allowedDirection.equals(ALLOW_ATTACKING_RIGHT)
&& !playerList.getPrevious().equals(playerDefending.getId())) {
// the defender is not the player to the right
return false;
}
return true;
}
}

View file

@ -0,0 +1,29 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.CardType;
import mage.constants.SubType;
public final class WallFlyingToken extends TokenImpl {
public WallFlyingToken() {
super("Wall Token", "0/4 white Wall creature token with defender and flying");
cardType.add(CardType.CREATURE);
subtype.add(SubType.WALL);
power = new MageInt(0);
toughness = new MageInt(4);
addAbility(DefenderAbility.getInstance());
addAbility(FlyingAbility.getInstance());
}
private WallFlyingToken(final WallFlyingToken token) {
super(token);
}
public WallFlyingToken copy() {
return new WallFlyingToken(this);
}
}