mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 13:02:06 -08:00
[LTR] Implement Witch-king of Angmar (#10563)
* Add card * Add TapSourceEffect * De-duplicate watcher logic * Abstract and fix(?) logic * Fix sacrifice targets * Controller instead of Owner * Add tests, fix, and refactor * Throw if controller not supported * Fix test (not supposed to start tapped)
This commit is contained in:
parent
008662be5e
commit
c8564efbb7
6 changed files with 202 additions and 28 deletions
|
|
@ -27,7 +27,8 @@ public enum TargetController {
|
|||
EACH_PLAYER,
|
||||
ENCHANTED,
|
||||
SOURCE_TARGETS,
|
||||
MONARCH;
|
||||
MONARCH,
|
||||
SOURCE_CONTROLLER;
|
||||
|
||||
private final OwnerPredicate ownerPredicate;
|
||||
private final PlayerPredicate playerPredicate;
|
||||
|
|
@ -78,6 +79,8 @@ public enum TargetController {
|
|||
case ENCHANTED:
|
||||
Permanent permanent = input.getSource().getSourcePermanentIfItStillExists(game);
|
||||
return permanent != null && input.getObject().isOwnedBy(permanent.getAttachedTo());
|
||||
case SOURCE_CONTROLLER:
|
||||
return card.isOwnedBy(input.getSource().getControllerId());
|
||||
case SOURCE_TARGETS:
|
||||
return card.isOwnedBy(input.getSource().getFirstTarget());
|
||||
case MONARCH:
|
||||
|
|
@ -119,8 +122,10 @@ public enum TargetController {
|
|||
game.getPlayer(playerId).hasOpponent(player.getId(), game);
|
||||
case NOT_YOU:
|
||||
return !player.getId().equals(playerId);
|
||||
case SOURCE_CONTROLLER:
|
||||
return player.getId().equals(input.getSource().getControllerId());
|
||||
case SOURCE_TARGETS:
|
||||
return player.equals(input.getSource().getFirstTarget());
|
||||
return player.getId().equals(input.getSource().getFirstTarget());
|
||||
case MONARCH:
|
||||
return player.getId().equals(game.getMonarchId());
|
||||
default:
|
||||
|
|
@ -162,6 +167,8 @@ public enum TargetController {
|
|||
case ENCHANTED:
|
||||
Permanent permanent = input.getSource().getSourcePermanentIfItStillExists(game);
|
||||
return permanent != null && input.getObject().isControlledBy(permanent.getAttachedTo());
|
||||
case SOURCE_CONTROLLER:
|
||||
return object.isControlledBy(input.getSource().getControllerId());
|
||||
case SOURCE_TARGETS:
|
||||
return object.isControlledBy(input.getSource().getFirstTarget());
|
||||
case MONARCH:
|
||||
|
|
|
|||
|
|
@ -10,61 +10,83 @@ import mage.watchers.common.PlayerDamagedBySourceWatcher;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* For use in abilities with this predicate:
|
||||
* "_ that dealt (combat) damage to _ this turn"
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class DamagedPlayerThisTurnPredicate implements ObjectSourcePlayerPredicate<Controllable> {
|
||||
|
||||
private final TargetController controller;
|
||||
private final TargetController playerDamaged;
|
||||
|
||||
public DamagedPlayerThisTurnPredicate(TargetController controller) {
|
||||
this.controller = controller;
|
||||
private final boolean combatDamageOnly;
|
||||
|
||||
public DamagedPlayerThisTurnPredicate(TargetController playerDamaged) {
|
||||
this(playerDamaged, false);
|
||||
}
|
||||
|
||||
public DamagedPlayerThisTurnPredicate(TargetController playerDamaged, boolean combatDamageOnly) {
|
||||
this.playerDamaged = playerDamaged;
|
||||
this.combatDamageOnly = combatDamageOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Controllable> input, Game game) {
|
||||
Controllable object = input.getObject();
|
||||
UUID objectId = input.getObject().getId();
|
||||
UUID playerId = input.getPlayerId();
|
||||
|
||||
switch (controller) {
|
||||
switch (playerDamaged) {
|
||||
case YOU:
|
||||
PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, playerId);
|
||||
if (watcher != null) {
|
||||
return watcher.hasSourceDoneDamage(object.getId(), game);
|
||||
}
|
||||
break;
|
||||
// that dealt damage to you this turn
|
||||
return playerDealtDamageBy(playerId, objectId, game);
|
||||
case SOURCE_CONTROLLER:
|
||||
// that dealt damage to this spell/ability's controller this turn
|
||||
UUID controllerId = input.getSource().getControllerId();
|
||||
return playerDealtDamageBy(controllerId, objectId, game);
|
||||
case OPPONENT:
|
||||
// that dealt damage to an opponent this turn
|
||||
for (UUID opponentId : game.getOpponents(playerId)) {
|
||||
watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, opponentId);
|
||||
if (watcher != null) {
|
||||
return watcher.hasSourceDoneDamage(object.getId(), game);
|
||||
if (playerDealtDamageBy(opponentId, objectId, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
return false;
|
||||
case NOT_YOU:
|
||||
// that dealt damage to another player this turn
|
||||
for (UUID notYouId : game.getState().getPlayersInRange(playerId, game)) {
|
||||
if (!notYouId.equals(playerId)) {
|
||||
watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, notYouId);
|
||||
if (watcher != null) {
|
||||
return watcher.hasSourceDoneDamage(object.getId(), game);
|
||||
if (playerDealtDamageBy(notYouId, objectId, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
return false;
|
||||
case ANY:
|
||||
// that dealt damage to a player this turn
|
||||
for (UUID anyId : game.getState().getPlayersInRange(playerId, game)) {
|
||||
watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, anyId);
|
||||
if (watcher != null) {
|
||||
return watcher.hasSourceDoneDamage(object.getId(), game);
|
||||
if (playerDealtDamageBy(anyId, objectId, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
throw new UnsupportedOperationException("TargetController not supported");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
private boolean playerDealtDamageBy(UUID playerId, UUID objectId, Game game) {
|
||||
PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, playerId);
|
||||
if (watcher == null) {
|
||||
return false;
|
||||
}
|
||||
if (combatDamageOnly) {
|
||||
return watcher.hasSourceDoneCombatDamage(objectId, game);
|
||||
}
|
||||
return watcher.hasSourceDoneDamage(objectId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Damaged player (" + controller.toString() + ')';
|
||||
return "Damaged player (" + playerDamaged.toString() + ')';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
|
|
@ -19,6 +19,7 @@ import mage.watchers.Watcher;
|
|||
public class PlayerDamagedBySourceWatcher extends Watcher {
|
||||
|
||||
private final Set<String> damageSourceIds = new HashSet<>();
|
||||
private final Set<String> combatDamageSourceIds = new HashSet<>();
|
||||
|
||||
public PlayerDamagedBySourceWatcher() {
|
||||
super(WatcherScope.PLAYER);
|
||||
|
|
@ -28,7 +29,11 @@ public class PlayerDamagedBySourceWatcher extends Watcher {
|
|||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
|
||||
if (event.getTargetId().equals(controllerId)) {
|
||||
damageSourceIds.add(CardUtil.getCardZoneString(null, event.getSourceId(), game));
|
||||
String sourceId = CardUtil.getCardZoneString(null, event.getSourceId(), game);
|
||||
damageSourceIds.add(sourceId);
|
||||
if (((DamagedEvent) event).isCombatDamage()) {
|
||||
combatDamageSourceIds.add(sourceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +50,10 @@ public class PlayerDamagedBySourceWatcher extends Watcher {
|
|||
return damageSourceIds.contains(CardUtil.getCardZoneString(null, sourceId, game));
|
||||
}
|
||||
|
||||
public boolean hasSourceDoneCombatDamage(UUID sourceId, Game game) {
|
||||
return combatDamageSourceIds.contains(CardUtil.getCardZoneString(null, sourceId, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue