forked from External/mage
Merge pull request 'master' (#22) from External/mage:master into master
All checks were successful
/ example-docker-compose (push) Successful in 28m47s
All checks were successful
/ example-docker-compose (push) Successful in 28m47s
Reviewed-on: #22
This commit is contained in:
commit
c8496d6bbe
133 changed files with 5368 additions and 224 deletions
|
|
@ -36,7 +36,6 @@ public class CastSecondSpellTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param zone What zone the ability can trigger from (see {@link mage.abilities.Ability#getZone})
|
||||
* @param effect What effect will happen when this ability triggers (see {@link mage.abilities.Ability#getEffects})
|
||||
* @param targetController Which player(s) to pay attention to
|
||||
|
|
@ -44,7 +43,7 @@ public class CastSecondSpellTriggeredAbility extends TriggeredAbilityImpl {
|
|||
* @param setTargetPointer Who to set the target pointer of the effects to. Only accepts NONE, PLAYER (the player who cast the spell), and SPELL (the spell which was cast)
|
||||
*/
|
||||
public CastSecondSpellTriggeredAbility(Zone zone, Effect effect, TargetController targetController,
|
||||
boolean optional, SetTargetPointer setTargetPointer) {
|
||||
boolean optional, SetTargetPointer setTargetPointer) {
|
||||
super(zone, effect, optional);
|
||||
if (targetController == TargetController.YOU) {
|
||||
this.addHint(hint);
|
||||
|
|
@ -54,7 +53,7 @@ public class CastSecondSpellTriggeredAbility extends TriggeredAbilityImpl {
|
|||
setTriggerPhrase(generateTriggerPhrase());
|
||||
}
|
||||
|
||||
private CastSecondSpellTriggeredAbility(final CastSecondSpellTriggeredAbility ability) {
|
||||
protected CastSecondSpellTriggeredAbility(final CastSecondSpellTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.targetController = ability.targetController;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class EntersBattlefieldOneOrMoreTriggeredAbility extends TriggeredAbility
|
|||
setTriggerPhrase(generateTriggerPhrase());
|
||||
}
|
||||
|
||||
private EntersBattlefieldOneOrMoreTriggeredAbility(final EntersBattlefieldOneOrMoreTriggeredAbility ability) {
|
||||
protected EntersBattlefieldOneOrMoreTriggeredAbility(final EntersBattlefieldOneOrMoreTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.filter = ability.filter;
|
||||
this.targetController = ability.targetController;
|
||||
|
|
|
|||
26
Mage/src/main/java/mage/abilities/common/FlurryAbility.java
Normal file
26
Mage/src/main/java/mage/abilities/common/FlurryAbility.java
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class FlurryAbility extends CastSecondSpellTriggeredAbility {
|
||||
|
||||
public FlurryAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, TargetController.YOU, false);
|
||||
this.setAbilityWord(AbilityWord.FLURRY);
|
||||
}
|
||||
|
||||
private FlurryAbility(final FlurryAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlurryAbility copy() {
|
||||
return new FlurryAbility(this);
|
||||
}
|
||||
}
|
||||
83
Mage/src/main/java/mage/abilities/common/RenewAbility.java
Normal file
83
Mage/src/main/java/mage/abilities/common/RenewAbility.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.ExileSourceFromGraveCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.Counter;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class RenewAbility extends ActivateAsSorceryActivatedAbility {
|
||||
|
||||
public RenewAbility(String manaString, Counter... counters) {
|
||||
super(Zone.GRAVEYARD, new RenewEffect(counters), new ManaCostsImpl<>(manaString));
|
||||
this.addCost(new ExileSourceFromGraveCost());
|
||||
this.addTarget(new TargetCreaturePermanent());
|
||||
this.setAbilityWord(AbilityWord.RENEW);
|
||||
}
|
||||
|
||||
private RenewAbility(final RenewAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenewAbility copy() {
|
||||
return new RenewAbility(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RenewEffect extends OneShotEffect {
|
||||
|
||||
private final List<Counter> counters = new ArrayList<>();
|
||||
|
||||
RenewEffect(Counter... counters) {
|
||||
super(Outcome.Benefit);
|
||||
for (Counter counter : counters) {
|
||||
this.counters.add(counter);
|
||||
}
|
||||
staticText = makeText(this.counters);
|
||||
}
|
||||
|
||||
private RenewEffect(final RenewEffect effect) {
|
||||
super(effect);
|
||||
for (Counter counter : effect.counters) {
|
||||
this.counters.add(counter.copy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenewEffect copy() {
|
||||
return new RenewEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
for (Counter counter : counters) {
|
||||
permanent.addCounters(counter, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String makeText(List<Counter> counters) {
|
||||
return "put " + CardUtil.concatWithAnd(
|
||||
counters.stream().map(Counter::getDescription).collect(Collectors.toList())
|
||||
) + " on target creature";
|
||||
}
|
||||
}
|
||||
|
|
@ -14,27 +14,23 @@ import mage.util.CardUtil;
|
|||
*
|
||||
* @author Jmlundeen
|
||||
*/
|
||||
public class CardsInExileCondition implements Condition
|
||||
{
|
||||
public class CardsInExileCondition implements Condition {
|
||||
private final ComparisonType type;
|
||||
private final int count;
|
||||
private final DynamicValue cardsInExileCount;
|
||||
|
||||
public CardsInExileCondition(ComparisonType type, int count)
|
||||
{
|
||||
public CardsInExileCondition(ComparisonType type, int count) {
|
||||
this(type, count, CardsInExileCount.ALL);
|
||||
}
|
||||
|
||||
public CardsInExileCondition(ComparisonType type, int count, DynamicValue cardsInExileCount)
|
||||
{
|
||||
public CardsInExileCondition(ComparisonType type, int count, DynamicValue cardsInExileCount) {
|
||||
this.type = type;
|
||||
this.count = count;
|
||||
this.cardsInExileCount = cardsInExileCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source)
|
||||
{
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int exileCards = cardsInExileCount.calculate(game, source, null);
|
||||
return ComparisonType.compare(exileCards, type, count);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SacrificedPermanentCondition implements Condition {
|
||||
|
||||
private final FilterPermanent filter;
|
||||
private boolean useThisWay = false;
|
||||
|
||||
public SacrificedPermanentCondition(FilterPermanent filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public SacrificedPermanentCondition(FilterPermanent filter, boolean useThisWay) {
|
||||
this.filter = filter;
|
||||
this.useThisWay = useThisWay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return CardUtil.castStream(source.getCosts()
|
||||
.stream(), SacrificeTargetCost.class)
|
||||
.map(SacrificeTargetCost::getPermanents)
|
||||
.flatMap(Collection::stream)
|
||||
.anyMatch(permanent -> filter.match(permanent, source.getControllerId(), source, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (useThisWay) {
|
||||
return "if " + filter.getMessage() + " was sacrificed this way";
|
||||
}
|
||||
return "if the sacrificed " + filter.getMessage();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class BeholdDragonCost extends CostImpl {
|
||||
|
||||
private static final FilterPermanent filterPermanent = new FilterControlledPermanent(SubType.DRAGON);
|
||||
private static final FilterCard filterCard = new FilterCard("a Dragon card");
|
||||
|
||||
static {
|
||||
filterCard.add(SubType.DRAGON.getPredicate());
|
||||
}
|
||||
|
||||
public BeholdDragonCost() {
|
||||
super();
|
||||
this.text = "behold a Dragon";
|
||||
}
|
||||
|
||||
private BeholdDragonCost(final BeholdDragonCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeholdDragonCost copy() {
|
||||
return new BeholdDragonCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return Optional
|
||||
.ofNullable(game.getPlayer(controllerId))
|
||||
.map(Player::getHand)
|
||||
.map(cards -> cards.count(filterCard, game) > 0)
|
||||
.orElse(false)
|
||||
|| game
|
||||
.getBattlefield()
|
||||
.contains(filterPermanent, controllerId, source, game, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player == null) {
|
||||
paid = false;
|
||||
return paid;
|
||||
}
|
||||
boolean hasPermanent = game
|
||||
.getBattlefield()
|
||||
.contains(filterPermanent, controllerId, source, game, 1);
|
||||
boolean hasHand = player.getHand().count(filterCard, game) > 0;
|
||||
boolean usePermanent;
|
||||
if (hasPermanent && hasHand) {
|
||||
usePermanent = player.chooseUse(
|
||||
Outcome.Neutral, "Choose a Dragon you control or reveal one from your hand?",
|
||||
null, "Choose controlled", "Reveal from hand", source, game);
|
||||
} else if (hasPermanent) {
|
||||
usePermanent = true;
|
||||
} else if (hasHand) {
|
||||
usePermanent = false;
|
||||
} else {
|
||||
paid = false;
|
||||
return paid;
|
||||
}
|
||||
if (usePermanent) {
|
||||
TargetPermanent target = new TargetPermanent(filterPermanent);
|
||||
target.withNotTarget(true);
|
||||
player.choose(Outcome.Neutral, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent == null) {
|
||||
paid = false;
|
||||
return paid;
|
||||
}
|
||||
game.informPlayers(player.getLogName() + " chooses to behold " + permanent.getLogName());
|
||||
paid = true;
|
||||
return true;
|
||||
}
|
||||
TargetCard target = new TargetCardInHand(filterCard);
|
||||
player.choose(Outcome.Neutral, player.getHand(), target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card == null) {
|
||||
paid = false;
|
||||
return paid;
|
||||
}
|
||||
player.revealCards(source, new CardsImpl(card), game);
|
||||
paid = true;
|
||||
return paid;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,15 +7,34 @@ import mage.constants.TurnPhase;
|
|||
import mage.game.Game;
|
||||
import mage.game.turn.TurnMod;
|
||||
|
||||
|
||||
public class AdditionalCombatPhaseEffect extends OneShotEffect {
|
||||
|
||||
private final int additionalPhases;
|
||||
|
||||
public AdditionalCombatPhaseEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.additionalPhases = 1;
|
||||
staticText = "after this phase, there is an additional combat phase";
|
||||
}
|
||||
|
||||
public AdditionalCombatPhaseEffect(int additionalPhases) {
|
||||
super(Outcome.Benefit);
|
||||
if (additionalPhases < 1) {
|
||||
throw new IllegalArgumentException("Number of additional phases must be at least 1");
|
||||
}
|
||||
if (additionalPhases == 1) {
|
||||
this.additionalPhases = 1;
|
||||
staticText = "after this phase, there is an additional combat phase";
|
||||
} else {
|
||||
this.additionalPhases = additionalPhases;
|
||||
staticText = "after this phase, there are " + additionalPhases + " additional combat phases";
|
||||
}
|
||||
}
|
||||
|
||||
protected AdditionalCombatPhaseEffect(final AdditionalCombatPhaseEffect effect) {
|
||||
super(effect);
|
||||
this.additionalPhases = effect.additionalPhases;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -25,7 +44,10 @@ public class AdditionalCombatPhaseEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
game.getState().getTurnMods().add(new TurnMod(game.getState().getActivePlayerId()).withExtraPhase(TurnPhase.COMBAT));
|
||||
for (int i = 0; i < additionalPhases; i++) {
|
||||
TurnMod combat = new TurnMod(game.getState().getActivePlayerId()).withExtraPhase(TurnPhase.COMBAT);
|
||||
game.getState().getTurnMods().add(combat);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,17 @@ public class CreateTokenEffect extends OneShotEffect {
|
|||
return lastAddedTokenIds;
|
||||
}
|
||||
|
||||
public void sacrificeTokensCreatedAtNextEndStep(Game game, Ability source) {
|
||||
for (UUID tokenId : this.getLastAddedTokenIds()) {
|
||||
Permanent tokenPermanent = game.getPermanent(tokenId);
|
||||
if (tokenPermanent != null) {
|
||||
SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect();
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(tokenPermanent, game));
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect), source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exileTokensCreatedAtNextEndStep(Game game, Ability source) {
|
||||
for (UUID tokenId : this.getLastAddedTokenIds()) {
|
||||
Permanent tokenPermanent = game.getPermanent(tokenId);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.SaddleAbility;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author Jmlundeen
|
||||
*/
|
||||
public class SaddleTargetMountEffect extends OneShotEffect {
|
||||
|
||||
public SaddleTargetMountEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Target Mount you control becomes saddled until end of turn";
|
||||
}
|
||||
|
||||
public SaddleTargetMountEffect(String rule) {
|
||||
super(Outcome.Benefit);
|
||||
staticText = rule;
|
||||
}
|
||||
|
||||
protected SaddleTargetMountEffect(final SaddleTargetMountEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SaddleTargetMountEffect copy() {
|
||||
return new SaddleTargetMountEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return SaddleAbility.applySaddle(game.getPermanent(getTargetPointer().getFirst(game, source)), game);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
this.token = token;
|
||||
this.loseType = loseType;
|
||||
staticText = text;
|
||||
this.dependencyTypes.add(DependencyType.BecomeCreature);
|
||||
}
|
||||
|
||||
protected BecomesCreatureAttachedEffect(final BecomesCreatureAttachedEffect effect) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public class BecomesCreatureIfVehicleEffect extends ContinuousEffectImpl {
|
|||
public BecomesCreatureIfVehicleEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||
this.staticText = "As long as enchanted permanent is a Vehicle, it's a creature in addition to its other types";
|
||||
this.dependencyTypes.add(DependencyType.BecomeCreature);
|
||||
}
|
||||
|
||||
protected BecomesCreatureIfVehicleEffect(final BecomesCreatureIfVehicleEffect effect) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ public class VehiclesBecomeArtifactCreatureEffect extends ContinuousEffectImpl {
|
|||
public VehiclesBecomeArtifactCreatureEffect(Duration duration) {
|
||||
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
|
||||
staticText = "Vehicles you control become artifact creatures until end of turn";
|
||||
this.dependencyTypes.add(DependencyType.BecomeCreature);
|
||||
}
|
||||
|
||||
private VehiclesBecomeArtifactCreatureEffect(final VehiclesBecomeArtifactCreatureEffect effect) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
package mage.abilities.effects.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.SpiritXXToken;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class EndureSourceEffect extends OneShotEffect {
|
||||
|
||||
private final int amount;
|
||||
|
||||
public EndureSourceEffect(int amount) {
|
||||
this(amount, "it");
|
||||
}
|
||||
|
||||
public EndureSourceEffect(int amount, String selfText) {
|
||||
super(Outcome.Benefit);
|
||||
staticText = selfText + " endures " + amount;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
private EndureSourceEffect(final EndureSourceEffect effect) {
|
||||
super(effect);
|
||||
this.amount = effect.amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EndureSourceEffect copy() {
|
||||
return new EndureSourceEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent != null && player.chooseUse(
|
||||
Outcome.BoostCreature, "Put " + CardUtil.numberToText(amount, "a") + " +1/+1 counter" +
|
||||
(amount > 1 ? "s" : "") + " on " + permanent.getName() + " or create " +
|
||||
CardUtil.addArticle("" + amount) + ' ' + amount + '/' + amount + " Spirit token?",
|
||||
null, "Add counters", "Create token", source, game
|
||||
)) {
|
||||
return permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game);
|
||||
}
|
||||
return new SpiritXXToken(amount).putOntoBattlefield(1, game, source);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.RedWarriorToken;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author balazskristof
|
||||
*/
|
||||
public class MobilizeAbility extends AttacksTriggeredAbility {
|
||||
|
||||
public MobilizeAbility(int count) {
|
||||
super(new MobilizeEffect(count), false, "Mobilize " + count + " <i>(Whenever this creature attacks, create "
|
||||
+ (count == 1 ? "a" : CardUtil.numberToText(count)) + " tapped and attacking 1/1 red Warrior creature "
|
||||
+ (count == 1 ? "token" : "tokens") + ". Sacrifice " + (count == 1 ? "it" : "them")
|
||||
+ " at the beginning of the next end step.)");
|
||||
}
|
||||
|
||||
protected MobilizeAbility(final MobilizeAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MobilizeAbility copy() {
|
||||
return new MobilizeAbility(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MobilizeEffect extends OneShotEffect {
|
||||
|
||||
private final int count;
|
||||
|
||||
MobilizeEffect(int count) {
|
||||
super(Outcome.Benefit);
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
private MobilizeEffect(final MobilizeEffect effect) {
|
||||
super(effect);
|
||||
this.count = effect.count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MobilizeEffect copy() {
|
||||
return new MobilizeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
CreateTokenEffect effect = new CreateTokenEffect(new RedWarriorToken(), this.count, true, true);
|
||||
effect.apply(game, source);
|
||||
effect.sacrificeTokensCreatedAtNextEndStep(game, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -48,6 +48,23 @@ public class SaddleAbility extends SimpleActivatedAbility {
|
|||
this.value = ability.value;
|
||||
}
|
||||
|
||||
public static boolean applySaddle(Permanent permanent, Game game) {
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
SaddleAbility saddleAbility = permanent.getAbilities().stream()
|
||||
.filter(a -> a instanceof SaddleAbility)
|
||||
.map(a -> (SaddleAbility) a)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (saddleAbility != null) {
|
||||
SaddleEventEffect effect = new SaddleEventEffect();
|
||||
effect.apply(game, saddleAbility);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SaddleAbility copy() {
|
||||
return new SaddleAbility(this);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public abstract class DeckValidator implements Serializable {
|
|||
maxCopiesMap.put("Slime Against Humanity", Integer.MAX_VALUE);
|
||||
maxCopiesMap.put("Templar Knight", Integer.MAX_VALUE);
|
||||
maxCopiesMap.put("Hare Apparent", Integer.MAX_VALUE);
|
||||
maxCopiesMap.put("Tempest Hawk", Integer.MAX_VALUE);
|
||||
maxCopiesMap.put("Once More with Feeling", 1);
|
||||
maxCopiesMap.put("Seven Dwarves", 7);
|
||||
maxCopiesMap.put("Nazgul", 9);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public enum AbilityWord {
|
|||
FATEFUL_HOUR("Fateful hour"),
|
||||
FATHOMLESS_DESCENT("Fathomless descent"),
|
||||
FEROCIOUS("Ferocious"),
|
||||
FLURRY("Flurry"),
|
||||
FORMIDABLE("Formidable"),
|
||||
GRANDEUR("Grandeur"),
|
||||
HATE("Hate"),
|
||||
|
|
@ -51,6 +52,7 @@ public enum AbilityWord {
|
|||
RADIANCE("Radiance"),
|
||||
RAID("Raid"),
|
||||
RALLY("Rally"),
|
||||
RENEW("Renew"),
|
||||
REVOLT("Revolt"),
|
||||
SECRET_COUNCIL("Secret council"),
|
||||
SPELL_MASTERY("Spell mastery"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.CrewAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
public class NalaarAetherjetToken extends TokenImpl{
|
||||
|
||||
public NalaarAetherjetToken(int xValue) {
|
||||
super("Nalaar Aetherjet", "X/X colorless Vehicle artifact token named Nalaar Aetherjet with flying and crew 2");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
subtype.add(SubType.VEHICLE);
|
||||
power = new MageInt(xValue);
|
||||
toughness = new MageInt(xValue);
|
||||
addAbility(FlyingAbility.getInstance());
|
||||
addAbility(new CrewAbility(2));
|
||||
}
|
||||
|
||||
private NalaarAetherjetToken(final NalaarAetherjetToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public NalaarAetherjetToken copy() {
|
||||
return new NalaarAetherjetToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author balazskristof
|
||||
*/
|
||||
public final class RedWarriorToken extends TokenImpl {
|
||||
|
||||
public RedWarriorToken() {
|
||||
super("Warrior Token", "1/1 red Warrior creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setRed(true);
|
||||
subtype.add(SubType.WARRIOR);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
}
|
||||
|
||||
private RedWarriorToken(final RedWarriorToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedWarriorToken copy() {
|
||||
return new RedWarriorToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
public class SpiritWarriorToken extends TokenImpl {
|
||||
|
||||
public SpiritWarriorToken() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public SpiritWarriorToken(int x) {
|
||||
super("Spirit Warrior Token", "X/X black and green Spirit Warrior creature token, where X is the greatest toughness among creatures you control");
|
||||
this.cardType.add(CardType.CREATURE);
|
||||
this.subtype.add(SubType.SPIRIT);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.color.setBlack(true);
|
||||
this.color.setGreen(true);
|
||||
this.power = new MageInt(x);
|
||||
this.toughness = new MageInt(x);
|
||||
}
|
||||
|
||||
private SpiritWarriorToken(final SpiritWarriorToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public SpiritWarriorToken copy() {
|
||||
return new SpiritWarriorToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author nantuko
|
||||
*/
|
||||
public final class SpiritXXToken extends TokenImpl {
|
||||
|
||||
public SpiritXXToken() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public SpiritXXToken(int amount) {
|
||||
super("Spirit Token", amount + '/' + amount + " white Spirit creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.SPIRIT);
|
||||
color.setWhite(true);
|
||||
power = new MageInt(amount);
|
||||
toughness = new MageInt(amount);
|
||||
}
|
||||
|
||||
private SpiritXXToken(final SpiritXXToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiritXXToken copy() {
|
||||
return new SpiritXXToken(this);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue