mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
- Improved TargetCardInASingleGraveyard to restrict all targets after the 1st to the same graveyard as the first chosen target
- Added slight documentation to Target and TargetCard - Minor cleanup to Unlicensedhearse
This commit is contained in:
parent
82708e4273
commit
eb63ea1e32
4 changed files with 86 additions and 17 deletions
|
@ -39,13 +39,15 @@ enum UnlicensedHearseValue implements DynamicValue {
|
|||
if (unlicensedHearse == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// use the source card, not the source object of the ability to grab the correct zcc
|
||||
ExileZone cardsExiledWithUnlicensedHearse
|
||||
= game.getExile().getExileZone(
|
||||
CardUtil.getExileZoneId(game, unlicensedHearse.getId(), unlicensedHearse.getZoneChangeCounter(game)));
|
||||
ExileZone cardsExiledWithUnlicensedHearse = game.getExile().getExileZone(
|
||||
CardUtil.getExileZoneId(game, unlicensedHearse.getId(), unlicensedHearse.getZoneChangeCounter(game))
|
||||
);
|
||||
if (cardsExiledWithUnlicensedHearse == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cardsExiledWithUnlicensedHearse.size();
|
||||
}
|
||||
|
||||
|
@ -72,8 +74,7 @@ public final class UnlicensedHearse extends CardImpl {
|
|||
this.toughness = new MageInt(0);
|
||||
|
||||
// {T}: Exile up to two target cards from a single graveyard.
|
||||
Ability ability
|
||||
= new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new TapSourceCost());
|
||||
Ability ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new TapSourceCost());
|
||||
ability.addTarget(new TargetCardInASingleGraveyard(0, 2, StaticFilters.FILTER_CARD_CARDS));
|
||||
this.addAbility(ability);
|
||||
|
||||
|
@ -81,8 +82,9 @@ public final class UnlicensedHearse extends CardImpl {
|
|||
this.addAbility(
|
||||
new SimpleStaticAbility(
|
||||
Zone.ALL,
|
||||
new SetPowerToughnessSourceEffect(UnlicensedHearseValue.instance, Duration.EndOfGame))
|
||||
.addHint(hint));
|
||||
new SetPowerToughnessSourceEffect(UnlicensedHearseValue.instance, Duration.EndOfGame)
|
||||
).addHint(hint)
|
||||
);
|
||||
|
||||
// Crew 2
|
||||
this.addAbility(new CrewAbility(2));
|
||||
|
|
|
@ -36,6 +36,14 @@ public interface Target extends Serializable {
|
|||
// methods for targets
|
||||
boolean canChoose(UUID sourceControllerId, Ability source, Game game);
|
||||
|
||||
/**
|
||||
* Returns a set of all possible targets that match the criteria of the implemented Target class.
|
||||
*
|
||||
* @param sourceControllerId UUID of the ability's controller
|
||||
* @param source Ability which requires the targets
|
||||
* @param game Current game
|
||||
* @return Set of the UUIDs of possible targets
|
||||
*/
|
||||
Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game);
|
||||
|
||||
boolean chooseTarget(Outcome outcome, UUID playerId, Ability source, Game game);
|
||||
|
|
|
@ -51,7 +51,8 @@ public class TargetCard extends TargetObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if there are enough {@link Card} that can be chosen.
|
||||
* Checks if there are enough {@link Card cards} in the appropriate zone that the player can choose from among them
|
||||
* or if they are autochosen since there are fewer than the minimum number.
|
||||
*
|
||||
* @param sourceControllerId - controller of the target event source
|
||||
* @param source
|
||||
|
@ -160,6 +161,7 @@ public class TargetCard extends TargetObject {
|
|||
switch (zone) {
|
||||
case HAND:
|
||||
for (Card card : player.getHand().getCards(filter, sourceControllerId, source, game)) {
|
||||
// TODO: Why for sourceId == null?
|
||||
if (sourceId == null || isNotTarget() || !game.replaceEvent(new TargetEvent(card, sourceId, sourceControllerId))) {
|
||||
possibleTargets.add(card.getId());
|
||||
}
|
||||
|
|
|
@ -2,12 +2,16 @@ package mage.target.common;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CommanderCardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.TargetEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -20,22 +24,75 @@ public class TargetCardInASingleGraveyard extends TargetCard {
|
|||
super(minNumTargets, maxNumTargets, Zone.GRAVEYARD, filter.copy().withMessage(filter.getMessage() + " from a single graveyard"));
|
||||
}
|
||||
|
||||
public TargetCardInASingleGraveyard(final TargetCardInASingleGraveyard target) {
|
||||
private TargetCardInASingleGraveyard(final TargetCardInASingleGraveyard target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
UUID firstTarget = this.getFirstTarget();
|
||||
if (firstTarget != null) {
|
||||
Card card = game.getCard(firstTarget);
|
||||
Card targetCard = game.getCard(id);
|
||||
if (card == null || targetCard == null
|
||||
|| !card.isOwnedBy(targetCard.getOwnerId())) {
|
||||
return false;
|
||||
if (firstTarget == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Card card = game.getCard(firstTarget);
|
||||
Card targetCard = game.getCard(id);
|
||||
if (card == null || targetCard == null || !card.isOwnedBy(targetCard.getOwnerId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.canTarget(id, source, game);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of UUIDs of all possible targets
|
||||
*
|
||||
* @param sourceControllerId UUID of the ability's controller
|
||||
* @param source Ability which requires the targets
|
||||
* @param game Current game
|
||||
* @return Set of the UUIDs of possible targets
|
||||
*/
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
UUID sourceId = source != null ? source.getSourceId() : null;
|
||||
|
||||
UUID controllerOfFirstTarget = null;
|
||||
|
||||
// If any targets have been chosen, get the UUID of the owner in order to limit the targets to that owner's graveyard
|
||||
if (!targets.isEmpty()) {
|
||||
for (UUID cardInGraveyardId : targets.keySet()) {
|
||||
Card targetCard = game.getCard(cardInGraveyardId);
|
||||
if (targetCard == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UUID ownerOfCardId = targetCard.getOwnerId();
|
||||
controllerOfFirstTarget = ownerOfCardId;
|
||||
break; // Only need the first UUID since they will all be the same
|
||||
}
|
||||
}
|
||||
return super.canTarget(id, source, game);
|
||||
|
||||
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
|
||||
// If the playerId of this iteration is not the same as that of any existing target, then continue
|
||||
// All cards must be from the same player's graveyard.
|
||||
if (controllerOfFirstTarget != null && !playerId.equals(controllerOfFirstTarget)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Card card : player.getGraveyard().getCards(filter, sourceControllerId, source, game)) {
|
||||
// TODO: Why for sourceId == null?
|
||||
if (sourceId == null || isNotTarget() || !game.replaceEvent(new TargetEvent(card, sourceId, sourceControllerId))) {
|
||||
possibleTargets.add(card.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return possibleTargets;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue