[LCI] Implement Fabrication Foundry; Unstable Glyphbridge (#11521)

* First pass at Fabrication Foundry

* misc cleanup

* First pass at Unstable Glyphbridge/Sandswirl Wanderglyph

* Set up backside correctly

* Fix Unstable Bridge cast condition

* Improve Fabrication Foundry to use Crew-like hint

* Fix equality check

Tested, though only manually.

Alongside the direct card implementations, I also:

-   Fix Oaken Siren's mana to not be able to pay for soft counterspells from artifact sources
-   Change PlayersAttackedThisTurnWatcher to follow the rules better and to have a separate section for planeswalkers' controllers who were attacked (needed for Sandswirl Wanderglyph)
-   Removed an unused constructor in ExileTargetCost (though I didn't end up using that cost in the end)
-   minor cleanup in CrewAbility
This commit is contained in:
ssk97 2023-12-10 18:30:20 -08:00 committed by GitHub
parent 3bc28d63c3
commit ec0166bf7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 449 additions and 14 deletions

View file

@ -31,10 +31,6 @@ public class ExileTargetCost extends CostImpl {
this.text = "exile " + target.getDescription();
}
public ExileTargetCost(TargetControlledPermanent target, boolean noText) {
this.addTarget(target);
}
public ExileTargetCost(ExileTargetCost cost) {
super(cost);
for (Permanent permanent : cost.permanents) {

View file

@ -152,8 +152,8 @@ class CrewCost extends CostImpl {
@Override
public String getMessage() {
// shows selected power
int selectedPower = this.targets.entrySet().stream()
.map(entry -> (game.getPermanent(entry.getKey())))
int selectedPower = this.targets.keySet().stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.mapToInt(p -> (getCrewPower(p, game)))
.sum();

View file

@ -3,6 +3,7 @@ package mage.watchers.common;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.PlayerList;
import mage.watchers.Watcher;
@ -18,6 +19,7 @@ public class PlayersAttackedThisTurnWatcher extends Watcher {
// how many players or opponents each player attacked this turn
private final Map<UUID, PlayerList> playersAttackedThisTurn = new HashMap<>();
private final Map<UUID, PlayerList> opponentsAttackedThisTurn = new HashMap<>();
private final Map<UUID, PlayerList> planeswalkerControllerAttackedThisTurn = new HashMap<>();
public PlayersAttackedThisTurnWatcher() {
super(WatcherScope.GAME);
@ -25,10 +27,10 @@ public class PlayersAttackedThisTurnWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.BEGINNING_PHASE_PRE) {
playersAttackedThisTurn.clear();
opponentsAttackedThisTurn.clear();
}
/*
Faramir, Prince of Ithilien:
Attacking a planeswalker you control or battle you're protecting doesn't count as attacking you. (2023-06-16)
*/
if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) {
@ -37,8 +39,8 @@ public class PlayersAttackedThisTurnWatcher extends Watcher {
if (playersAttacked == null) {
playersAttacked = new PlayerList();
}
UUID playerDefender = game.getCombat().getDefendingPlayerId(event.getSourceId(), game);
if (playerDefender != null
UUID playerDefender = event.getTargetId();
if (playerDefender != null && game.getPlayer(playerDefender) != null
&& !playersAttacked.contains(playerDefender)) {
playersAttacked.add(playerDefender);
}
@ -49,13 +51,26 @@ public class PlayersAttackedThisTurnWatcher extends Watcher {
if (opponentsAttacked == null) {
opponentsAttacked = new PlayerList();
}
UUID opponentDefender = game.getCombat().getDefendingPlayerId(event.getSourceId(), game);
UUID opponentDefender = event.getTargetId();
if (opponentDefender != null
&& game.getOpponents(event.getPlayerId()).contains(opponentDefender)
&& !opponentsAttacked.contains(opponentDefender)) {
opponentsAttacked.add(opponentDefender);
}
opponentsAttackedThisTurn.putIfAbsent(event.getPlayerId(), opponentsAttacked);
//Planeswalker controllers
PlayerList controllersAttacked = planeswalkerControllerAttackedThisTurn.get(event.getPlayerId());
if (controllersAttacked == null) {
controllersAttacked = new PlayerList();
}
Permanent permanent = game.getPermanent(event.getTargetId());
UUID controllingDefender = game.getCombat().getDefendingPlayerId(event.getSourceId(), game);
if (controllingDefender != null && permanent != null && permanent.isPlaneswalker(game)
&& !controllersAttacked.contains(controllingDefender)) {
controllersAttacked.add(controllingDefender);
}
planeswalkerControllerAttackedThisTurn.putIfAbsent(event.getPlayerId(), controllersAttacked);
}
}
@ -63,6 +78,12 @@ public class PlayersAttackedThisTurnWatcher extends Watcher {
PlayerList defendersList = playersAttackedThisTurn.getOrDefault(attacker, null);
return defendersList != null && defendersList.contains(defender);
}
public boolean hasPlayerAttackedPlayerOrControlledPlaneswalker(UUID attacker, UUID defender){
PlayerList defendersList = playersAttackedThisTurn.getOrDefault(attacker, null);
PlayerList planeswalkerControllersList = planeswalkerControllerAttackedThisTurn.getOrDefault(attacker, null);
return (defendersList != null && defendersList.contains(defender)) ||
(planeswalkerControllersList != null && planeswalkerControllersList.contains(defender));
}
public int getAttackedPlayersCount(UUID playerID) {
PlayerList defendersList = playersAttackedThisTurn.getOrDefault(playerID, null);
@ -79,4 +100,12 @@ public class PlayersAttackedThisTurnWatcher extends Watcher {
}
return 0;
}
@Override
public void reset() {
super.reset();
playersAttackedThisTurn.clear();
opponentsAttackedThisTurn.clear();
planeswalkerControllerAttackedThisTurn.clear();
}
}