foul-magics/Mage/src/main/java/mage/abilities/keyword/HideawayAbility.java

179 lines
5.9 KiB
Java

package mage.abilities.keyword;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import mage.watchers.Watcher;
import java.util.*;
/**
* @author LevelX2
* <p>
* 702.74. Hideaway 702.74a Hideaway represents a static ability and a triggered
* ability. "Hideaway" means "This permanent enters the battlefield tapped" and
* "When this permanent enters the battlefield, look at the top four cards of
* your library. Exile one of them face down and put the rest on the bottom of
* your library in any order. The exiled card gains 'Any player who has
* controlled the permanent that exiled this card may look at this card in the
* exile zone.'"
*/
public class HideawayAbility extends EntersBattlefieldTriggeredAbility {
private final int amount;
public HideawayAbility(int amount) {
super(new HideawayExileEffect(amount));
this.amount = amount;
this.addWatcher(new HideawayWatcher());
}
private HideawayAbility(final HideawayAbility ability) {
super(ability);
this.amount = ability.amount;
}
@Override
public String getRule() {
return "Hideaway " + this.amount + " <i>(When this permanent enters the battlefield, look at the top "
+ CardUtil.numberToText(this.amount) + " cards of your library, exile one face down, " +
"then put the rest on the bottom of your library in a random order.)</i>";
}
@Override
public HideawayAbility copy() {
return new HideawayAbility(this);
}
}
class HideawayExileEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("card to exile face down");
private final int amount;
HideawayExileEffect(int amount) {
super(Outcome.Benefit);
this.amount = amount;
}
private HideawayExileEffect(final HideawayExileEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
public HideawayExileEffect copy() {
return new HideawayExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, amount));
if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(Zone.LIBRARY, filter);
target.setNotTarget(true);
controller.choose(Outcome.Detriment, cards, target, source, game);
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
controller.moveCardsToExile(
card, source, game, false,
CardUtil.getExileZoneId(game, source),
"Hideaway (" + CardUtil.getSourceName(game, source) + ')'
);
game.addEffect(new HideawayLookAtFaceDownCardEffect().setTargetPointer(new FixedTarget(card, game)), source);
card.setFaceDown(true, game);
}
cards.retainZone(Zone.LIBRARY, game);
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
return true;
}
}
class HideawayLookAtFaceDownCardEffect extends AsThoughEffectImpl {
HideawayLookAtFaceDownCardEffect() {
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
}
private HideawayLookAtFaceDownCardEffect(final HideawayLookAtFaceDownCardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public HideawayLookAtFaceDownCardEffect copy() {
return new HideawayLookAtFaceDownCardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return Objects.equals(objectId, getTargetPointer().getFirst(game, source))
&& HideawayWatcher.check(affectedControllerId, source, game);
}
}
class HideawayWatcher extends Watcher {
private final Map<MageObjectReference, Set<UUID>> morMap = new HashMap<>();
HideawayWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
Permanent permanent;
UUID playerId;
switch (event.getType()) {
case GAINED_CONTROL:
permanent = game.getPermanent(event.getTargetId());
playerId = event.getPlayerId();
break;
case ENTERS_THE_BATTLEFIELD:
permanent = ((EntersTheBattlefieldEvent) event).getTarget();
playerId = permanent.getControllerId();
break;
case BEGINNING_PHASE_PRE:
if (game.getTurnNum() == 1) {
morMap.clear();
}
default:
return;
}
morMap.computeIfAbsent(new MageObjectReference(permanent, game), x -> new HashSet<>()).add(playerId);
}
static boolean check(UUID playerId, Ability source, Game game) {
return game
.getState()
.getWatcher(HideawayWatcher.class)
.morMap
.getOrDefault(new MageObjectReference(source), Collections.emptySet())
.contains(playerId);
}
}