forked from External/mage
[WHO] Implement 4 cards, create generic EachOpponentPermanentTargetsAdjuster (#11886)
* Implement Bigger on the Inside * implement Reverse the Polarity * Implement Sontaran General * Implement Everything Comes to Dust
This commit is contained in:
parent
26ac305a7f
commit
d886b3e450
30 changed files with 479 additions and 585 deletions
|
|
@ -13,6 +13,8 @@ import mage.players.Player;
|
|||
import mage.util.CardUtil;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author xenohedron
|
||||
*/
|
||||
|
|
@ -21,17 +23,25 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl {
|
|||
private int spellsCast;
|
||||
private final Ability ability;
|
||||
private final FilterCard filter;
|
||||
private final TargetController targetController;
|
||||
|
||||
public NextSpellCastHasAbilityEffect(Ability ability) {
|
||||
this(ability, StaticFilters.FILTER_CARD);
|
||||
}
|
||||
|
||||
public NextSpellCastHasAbilityEffect(Ability ability, FilterCard filter) {
|
||||
this(ability, StaticFilters.FILTER_CARD, TargetController.SOURCE_CONTROLLER);
|
||||
}
|
||||
public NextSpellCastHasAbilityEffect(Ability ability, TargetController targetController) {
|
||||
this(ability, StaticFilters.FILTER_CARD, targetController);
|
||||
}
|
||||
public NextSpellCastHasAbilityEffect(Ability ability, FilterCard filter, TargetController targetController) {
|
||||
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
this.ability = ability;
|
||||
this.filter = filter;
|
||||
this.targetController = targetController;
|
||||
staticText = "the next " + filter.getMessage().replace("card", "spell")
|
||||
+ " you cast this turn has " + CardUtil.getTextWithFirstCharLowerCase(CardUtil.stripReminderText(ability.getRule()));
|
||||
+ (targetController == TargetController.SOURCE_CONTROLLER ? " you cast" : " target player casts")
|
||||
+ " this turn has " + CardUtil.getTextWithFirstCharLowerCase(CardUtil.stripReminderText(ability.getRule()));
|
||||
}
|
||||
|
||||
private NextSpellCastHasAbilityEffect(final NextSpellCastHasAbilityEffect effect) {
|
||||
|
|
@ -39,6 +49,7 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl {
|
|||
this.spellsCast = effect.spellsCast;
|
||||
this.ability = effect.ability;
|
||||
this.filter = effect.filter;
|
||||
this.targetController = effect.targetController;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -57,17 +68,28 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
UUID playerId;
|
||||
switch (targetController){
|
||||
case SOURCE_TARGETS:
|
||||
playerId = source.getFirstTarget();
|
||||
break;
|
||||
case SOURCE_CONTROLLER:
|
||||
playerId = source.getControllerId();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Value for targetController in NextSpellCastHasAbilityEffect not supported: " + targetController);
|
||||
}
|
||||
Player player = game.getPlayer(playerId);
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
if (player == null || watcher == null) {
|
||||
return false;
|
||||
}
|
||||
//check if a spell was cast before
|
||||
if (watcher.getCount(source.getControllerId()) > spellsCast) {
|
||||
if (watcher.getCount(playerId) > spellsCast) {
|
||||
discard(); // only one use
|
||||
return false;
|
||||
}
|
||||
for (Card card : game.getExile().getAllCardsByRange(game, source.getControllerId())) {
|
||||
for (Card card : game.getExile().getAllCardsByRange(game, playerId)) {
|
||||
if (filter.match(card, game)) {
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
}
|
||||
|
|
@ -94,7 +116,7 @@ public class NextSpellCastHasAbilityEffect extends ContinuousEffectImpl {
|
|||
.forEach(card -> game.getState().addOtherAbility(card, ability));
|
||||
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (!(stackObject instanceof Spell) || !stackObject.isControlledBy(source.getControllerId())) {
|
||||
if (!(stackObject instanceof Spell) || !stackObject.isControlledBy(playerId)) {
|
||||
continue;
|
||||
}
|
||||
// TODO: Distinguish "you cast" to exclude copies
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package mage.target.targetadjustment;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author notgreat
|
||||
*/
|
||||
public class EachOpponentPermanentTargetsAdjuster implements TargetAdjuster {
|
||||
private final TargetPermanent blueprintTarget;
|
||||
|
||||
/**
|
||||
* Duplicates the permanent target for each opponent.
|
||||
* Filtering of permanent's controllers will be handled inside, so
|
||||
* do not pass a blueprint target with a controller restriction filter/predicate.
|
||||
*
|
||||
* @param blueprintTarget The target to be duplicated per opponent
|
||||
*/
|
||||
public EachOpponentPermanentTargetsAdjuster(TargetPermanent blueprintTarget) {
|
||||
this.blueprintTarget = blueprintTarget.copy(); //Defensively copy the blueprint to ensure immutability
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
ability.getTargets().clear();
|
||||
for (UUID opponentId : game.getOpponents(ability.getControllerId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent == null) {
|
||||
continue;
|
||||
}
|
||||
TargetPermanent newTarget = blueprintTarget.copy();
|
||||
Filter<Permanent> filter = newTarget.getFilter();
|
||||
filter.add(new ControllerIdPredicate(opponentId));
|
||||
if (newTarget.canChoose(ability.getControllerId(), ability, game)) {
|
||||
filter.setMessage(filter.getMessage()+" controlled by " + opponent.getLogName());
|
||||
ability.addTarget(newTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,5 +11,6 @@ import java.io.Serializable;
|
|||
@FunctionalInterface
|
||||
public interface TargetAdjuster extends Serializable {
|
||||
|
||||
// Warning: This is not Copyable, do not use changeable data inside (only use static objects like Filter)
|
||||
void adjustTargets(Ability ability, Game game);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue