Merge pull request #4940 from magefree/master

merge
This commit is contained in:
theelk801 2018-05-14 14:08:30 -04:00 committed by GitHub
commit fbde510bac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
935 changed files with 13628 additions and 12155 deletions

View file

@ -42,7 +42,7 @@ import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DynamicManaEffect;
import mage.abilities.effects.mana.DynamicManaEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.Card;
@ -157,6 +157,8 @@ public abstract class AbilityImpl implements Ability {
public void newId() {
if (!(this instanceof MageSingleton)) {
this.id = UUID.randomUUID();
// this.sourceObject = null;
// this.sourceObjectZoneChangeCounter = -1;
}
getEffects().newId();
}
@ -1211,7 +1213,7 @@ public abstract class AbilityImpl implements Ability {
@Override
public Permanent getSourcePermanentIfItStillExists(Game game) {
if (sourceObject == null) {
if (sourceObject == null || !sourceObject.getId().equals(getSourceId())) {
setSourceObject(game.getObject(getSourceId()), game);
}
if (sourceObject instanceof Permanent) {

View file

@ -250,6 +250,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
return false;
}
@Override
public void setMayActivate(TargetController mayActivate) {
this.mayActivate = mayActivate;
}

View file

@ -79,6 +79,6 @@ public class ConstellationAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return new StringBuilder("<i>Constellation</i> - Whenever {this} or another enchantment enters the battlefield under your control, ").append(super.getRule()).toString();
return new StringBuilder("<i>Constellation</i> &mdash; Whenever {this} or another enchantment enters the battlefield under your control, ").append(super.getRule()).toString();
}
}

View file

@ -86,7 +86,7 @@ public class KinshipAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return new StringBuilder("<i>Kinship</i> - At the beginning of your upkeep, ").append(super.getRule()).toString();
return new StringBuilder("<i>Kinship</i> &mdash; At the beginning of your upkeep, ").append(super.getRule()).toString();
}
}

View file

@ -46,12 +46,12 @@ import mage.constants.Zone;
public class LieutenantAbility extends SimpleStaticAbility {
public LieutenantAbility(ContinuousEffect effect) {
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.instance, "<i>Lieutenant</i> - As long as you control your commander, {this} gets +2/+2"));
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.instance, "<i>Lieutenant</i> &mdash; As long as you control your commander, {this} gets +2/+2"));
this.addEffect(new ConditionalContinuousEffect(effect, CommanderInPlayCondition.instance, effect.getText(null)));
}
public LieutenantAbility(Effects effects) {
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.instance, "<i>Lieutenant</i> - As long as you control your commander, {this} gets +2/+2"));
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.instance, "<i>Lieutenant</i> &mdash; As long as you control your commander, {this} gets +2/+2"));
for (Effect effect : effects) {
this.addEffect(new ConditionalContinuousEffect((ContinuousEffect) effect, CommanderInPlayCondition.instance, effect.getText(null)));
}

View file

@ -68,7 +68,7 @@ public class StriveAbility extends SimpleStaticAbility {
@Override
public String getRule() {
return new StringBuilder("<i>Strive</i> - {this} costs ").append(striveCost).append(" more to cast for each target beyond the first.").toString();
return new StringBuilder("<i>Strive</i> &mdash; {this} costs ").append(striveCost).append(" more to cast for each target beyond the first.").toString();
}
}

View file

@ -1,18 +1,27 @@
package mage.abilities.common;
import mage.abilities.condition.common.LegendaryCondition;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
* @author JRHerlehy
* Created on 4/8/18.
* @author JRHerlehy Created on 4/8/18.
*/
public class LegendarySpellAbility extends SimpleStaticAbility {
public LegendarySpellAbility() {
super(Zone.ALL, new CastOnlyIfConditionIsTrueEffect(LegendaryCondition.instance));
super(Zone.ALL, new LegendarySpellAbilityCheckEffect());
this.setRuleAtTheTop(true);
this.getEffects().get(0).setText("<i>(You may cast a legendary sorcery only if you control a legendary creature or planeswalker.)</i>");
}
private LegendarySpellAbility(final LegendarySpellAbility ability) {
@ -24,3 +33,46 @@ public class LegendarySpellAbility extends SimpleStaticAbility {
return new LegendarySpellAbility(this);
}
}
class LegendarySpellAbilityCheckEffect extends ContinuousRuleModifyingEffectImpl {
private static final FilterPermanent filter = new FilterPermanent("legendary creature or planeswalker");
static {
filter.add(
Predicates.and(
new SupertypePredicate(SuperType.LEGENDARY),
Predicates.or(
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.PLANESWALKER)
)
)
);
}
public LegendarySpellAbilityCheckEffect() {
super(Duration.EndOfGame, Outcome.Detriment);
staticText = "<i>(You may cast a legendary sorcery only if you control a legendary creature or planeswalker.)</i>";
}
private LegendarySpellAbilityCheckEffect(final LegendarySpellAbilityCheckEffect effect) {
super(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.CAST_SPELL;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return event.getSourceId().equals(source.getSourceId())
&& !game.getBattlefield().contains(filter, event.getPlayerId(), 1, game);
}
@Override
public LegendarySpellAbilityCheckEffect copy() {
return new LegendarySpellAbilityCheckEffect(this);
}
}

View file

@ -1,46 +0,0 @@
package mage.abilities.condition.common;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
/**
* @author JRHerlehy
* Created on 4/7/18.
*/
public enum LegendaryCondition implements Condition {
instance;
private static final FilterPermanent filter = new FilterPermanent("legendary creature or planeswalker");
static {
filter.add(
Predicates.and(
new SupertypePredicate(SuperType.LEGENDARY),
Predicates.or(
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.PLANESWALKER)
)
)
);
}
@Override
public boolean apply(Game game, Ability source) {
return game.getBattlefield().contains(filter, source.getControllerId(), 1, game);
}
@Override
public String toString() {
return super.toString();
}
}

View file

@ -63,7 +63,7 @@ public class ExileFromStackCost extends CostImpl {
}
String spellName = spellToExile.getName();
if (spellToExile.isCopy()) {
game.getStack().remove(spellToExile);
game.getStack().remove(spellToExile, game);
} else {
spellToExile.moveToExile(null, "", ability.getSourceId(), game);
}

View file

@ -30,8 +30,8 @@ package mage.abilities.decorator;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.choices.ChoiceColor;
import mage.game.Game;
import mage.players.Player;
@ -73,31 +73,7 @@ public class ConditionalManaEffect extends ManaEffect {
if (controller == null) {
return false;
}
if (condition.apply(game, source)) {
effect.setTargetPointer(this.targetPointer);
} else if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
}
Mana mana = getMana(game, source);
if (mana == null) {
return false;
}
if (mana.getAny() > 0) {
int amount = mana.getAny();
ChoiceColor choice = new ChoiceColor(true);
Mana createdMana = null;
if (controller.choose(outcome, choice, game)) {
createdMana = choice.getMana(amount);
}
if (createdMana == null) {
return false;
}
mana = createdMana;
// because the mana type is now choosen, fire the event with the mana information
checkToFirePossibleEvents(mana, game, source);
}
controller.getManaPool().addMana(mana, game, source);
controller.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
@ -107,12 +83,25 @@ public class ConditionalManaEffect extends ManaEffect {
}
@Override
public Mana getMana(Game game, Ability source) {
Mana mana = null;
public Mana produceMana(boolean netMana, Game game, Ability source) {
Mana mana = new Mana();
if (condition.apply(game, source)) {
mana = effect.getMana();
mana = effect.getManaTemplate().copy();
} else if (otherwiseEffect != null) {
mana = otherwiseEffect.getMana();
mana = otherwiseEffect.getManaTemplate().copy();
}
if (mana.getAny() > 0) {
int amount = mana.getAny();
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return mana;
}
ChoiceColor choice = new ChoiceColor(true);
if (controller.choose(outcome, choice, game)) {
mana.setAny(0);
mana.add(choice.getMana(amount));
}
checkToFirePossibleEvents(mana, game, source);
}
return mana;
}

View file

@ -48,7 +48,7 @@ public class OpponentsLostLifeCount implements DynamicValue {
public int calculate(Game game, UUID controllerId) {
PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName());
if (watcher != null) {
return watcher.getAllOppLifeLost(controllerId);
return watcher.getAllOppLifeLost(controllerId, game);
}
return 0;
}

View file

@ -8,18 +8,30 @@ import mage.game.Game;
public class SignInversionDynamicValue implements DynamicValue {
private final DynamicValue value;
private final boolean canBePositive;
public SignInversionDynamicValue(DynamicValue value) {
this(value, true);
}
public SignInversionDynamicValue(DynamicValue value, boolean canBePositive) {
this.value = value.copy();
this.canBePositive = canBePositive;
}
SignInversionDynamicValue(final SignInversionDynamicValue dynamicValue) {
this.value = dynamicValue.value.copy();
this.canBePositive = dynamicValue.canBePositive;
}
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
return -1 * value.calculate(game, sourceAbility, effect);
int amount = value.calculate(game, sourceAbility, effect);
if (amount >= 0 || canBePositive) {
return -1 * amount;
} else {
return 0;
}
}
@Override

View file

@ -926,6 +926,14 @@ public class ContinuousEffects implements Serializable {
while (!done) { // loop needed if a added effect adds again an effect (e.g. Level 5- of Joraga Treespeaker)
done = true;
layer = filterLayeredEffects(activeLayerEffects, Layer.AbilityAddingRemovingEffects_6);
// debug
/*
System.out.println(game.getTurn() + ", " + game.getPhase() + ": " + "need apply " + layer.stream()
.map((eff) -> {return eff.getClass().getName().replaceAll(".+\\.(.+)", "$1");})
.collect(Collectors.joining(", ")));
*/
for (ContinuousEffect effect : layer) {
if (activeLayerEffects.contains(effect) && !appliedEffects.contains(effect.getId())) { // Effect does still exist and was not applied yet
Set<UUID> dependentTo = effect.isDependentTo(layer);

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.effects;
import mage.MageObject;
import mage.abilities.Ability;
import mage.constants.Duration;
import mage.constants.EffectType;
@ -44,26 +45,34 @@ import mage.target.Target;
*/
public abstract class RedirectionEffect extends ReplacementEffectImpl {
protected Target redirectTarget;
protected int amountToRedirect;
protected boolean oneUsage;
public RedirectionEffect(Duration duration) {
this(duration, Integer.MAX_VALUE, false);
public enum UsageType {
ACCORDING_DURATION,
ONE_USAGE_ABSOLUTE,
ONE_USAGE_AT_THE_SAME_TIME; // all damage dealt at the same time
}
public RedirectionEffect(Duration duration, int amountToRedirect, boolean oneUsage) {
protected Target redirectTarget;
protected int amountToRedirect;
protected UsageType usageType;
protected int applyEffectsCounter;
public RedirectionEffect(Duration duration) {
this(duration, Integer.MAX_VALUE, UsageType.ACCORDING_DURATION);
applyEffectsCounter = -1;
}
public RedirectionEffect(Duration duration, int amountToRedirect, UsageType usageType) {
super(duration, Outcome.RedirectDamage);
this.effectType = EffectType.REDIRECTION;
this.amountToRedirect = amountToRedirect;
this.oneUsage = oneUsage;
this.usageType = usageType;
}
public RedirectionEffect(final RedirectionEffect effect) {
super(effect);
this.redirectTarget = effect.redirectTarget;
this.amountToRedirect = effect.amountToRedirect;
this.oneUsage = effect.oneUsage;
this.usageType = effect.usageType;
}
@Override
@ -79,26 +88,38 @@ public abstract class RedirectionEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
int damageToRedirect = event.getAmount();
if (damageToRedirect < 1) { // if multiple replacement effect apply, the rest damage can be 0, so the effect is not applied/replaced
return false;
}
String sourceLogName = source != null ? game.getObject(source.getSourceId()).getLogName() + ": " : "";
DamageEvent damageEvent = (DamageEvent) event;
int restDamage = 0;
int damageToRedirect = event.getAmount();
if (damageEvent.getAmount() > amountToRedirect) {
restDamage = damageEvent.getAmount() - amountToRedirect;
damageToRedirect = amountToRedirect;
}
if (damageToRedirect > 0 && oneUsage) {
this.discard();
if (damageToRedirect > 0 && usageType != UsageType.ACCORDING_DURATION) {
if (UsageType.ONE_USAGE_ABSOLUTE == usageType) {
this.discard();
}
if (applyEffectsCounter > 0) {
if (applyEffectsCounter < game.getState().getApplyEffectsCounter()) {
this.discard();
}
} else {
applyEffectsCounter = game.getState().getApplyEffectsCounter();
}
}
Permanent permanent = game.getPermanent(redirectTarget.getFirstTarget());
if (permanent != null) {
permanent.damage(damageToRedirect, event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
game.informPlayers(sourceLogName + "Redirected " + damageToRedirect + " damage to " + permanent.getLogName());
game.informPlayers(sourceLogName + "Redirected " + damageToRedirect + " damage" + getRedirectedFromText(event, game) + " to " + permanent.getLogName());
} else {
Player player = game.getPlayer(redirectTarget.getFirstTarget());
if (player != null) {
player.damage(damageToRedirect, event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
game.informPlayers(sourceLogName + "Redirected " + damageToRedirect + " damage to " + player.getLogName());
game.informPlayers(sourceLogName + "Redirected " + damageToRedirect + " damage" + getRedirectedFromText(event, game) + " to " + player.getLogName());
}
}
if (restDamage > 0) {
@ -108,4 +129,16 @@ public abstract class RedirectionEffect extends ReplacementEffectImpl {
return true;
}
private String getRedirectedFromText(GameEvent event, Game game) {
Player player = game.getPlayer(event.getTargetId());
if (player != null) {
return " from " + player.getLogName();
}
MageObject mageObject = game.getObject(event.getTargetId());
if (mageObject != null) {
return " from " + mageObject.getLogName();
}
return "";
}
}

View file

@ -1,61 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class AddConditionalColorlessManaEffect extends ManaEffect {
private final int amount;
private final ConditionalManaBuilder manaBuilder;
public AddConditionalColorlessManaEffect(int amount, ConditionalManaBuilder manaBuilder) {
super();
this.amount = amount;
this.manaBuilder = manaBuilder;
staticText = "Add " + String.format(String.format("%%%ds", amount), " ").replace(" ", "{C}")
+ ". " + manaBuilder.getRule();
}
public AddConditionalColorlessManaEffect(final AddConditionalColorlessManaEffect effect) {
super(effect);
this.amount = effect.amount;
this.manaBuilder = effect.manaBuilder;
}
@Override
public AddConditionalColorlessManaEffect copy() {
return new AddConditionalColorlessManaEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana getMana(Game game, Ability source) {
return manaBuilder.setMana(Mana.ColorlessMana(amount), source, game).build();
}
public Mana getMana() {
return Mana.ColorlessMana(amount);
}
}

View file

@ -1,49 +0,0 @@
package mage.abilities.effects.common;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.choices.ChoiceColor;
import mage.game.Game;
import mage.players.Player;
/**
*
* Created by Galatolol
*/
public class AddManaOfAnyColorToManaPoolTargetPlayerEffect extends ManaEffect {
public AddManaOfAnyColorToManaPoolTargetPlayerEffect(String textManaPoolOwner) {
super();
this.staticText = (textManaPoolOwner.equals("their") ? "that player adds " : "add ") + "one mana of any color" + " to " + textManaPoolOwner + " mana pool";
}
public AddManaOfAnyColorToManaPoolTargetPlayerEffect(final AddManaOfAnyColorToManaPoolTargetPlayerEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
UUID playerId = (UUID) game.getState().getValue(source.getSourceId() + "_player");
Player player = game.getPlayer(playerId);
ChoiceColor choice = new ChoiceColor();
if (player != null && player.choose(outcome, choice, game)) {
Mana mana = choice.getMana(1);
checkToFirePossibleEvents(mana, game, source);
player.getManaPool().addMana(mana, game, source);
return true;
}
return false;
}
@Override
public AddManaOfAnyColorToManaPoolTargetPlayerEffect copy() {
return new AddManaOfAnyColorToManaPoolTargetPlayerEffect(this);
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
import java.util.Objects;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
@ -36,8 +37,6 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import java.util.Objects;
/**
*
* @author jeffwadsworth
@ -67,6 +66,17 @@ public class CantBeRegeneratedSourceEffect extends ContinuousRuleModifyingEffect
return event.getType() == EventType.REGENERATE;
}
@Override
public void init(Ability source, Game game) {
super.init(source, game); //To change body of generated methods, choose Tools | Templates.
if (duration.isOnlyValidIfNoZoneChange()) {
// If source permanent is no longer onto battlefield discard the effect
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
}
}
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return Objects.equals(source.getSourceId(), event.getTargetId());

View file

@ -63,7 +63,7 @@ public class DestroySourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, noRegen);
return true;

View file

@ -71,6 +71,7 @@ public class DoIfCostPaid extends OneShotEffect {
}
message = getCostText() + " and " + effectText + '?';
message = Character.toUpperCase(message.charAt(0)) + message.substring(1);
CardUtil.replaceSourceName(message, mageObject.getName());
} else {
message = chooseUseText;
}
@ -79,6 +80,7 @@ public class DoIfCostPaid extends OneShotEffect {
if (cost.canPay(source, source.getSourceId(), player.getId(), game)
&& executingEffects.size() > 0 && (!optional || player.chooseUse(executingEffects.get(0).getOutcome(), message, source, game))) {
cost.clearPaid();
int bookmark = game.bookmarkState();
if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) {
for (Effect effect : executingEffects) {
effect.setTargetPointer(this.targetPointer);
@ -89,13 +91,17 @@ public class DoIfCostPaid extends OneShotEffect {
}
}
player.resetStoredBookmark(game); // otherwise you can e.g. undo card drawn with Mentor of the Meek
} else if (!otherwiseEffects.isEmpty()) {
for (Effect effect : otherwiseEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {
result &= effect.apply(game, source);
} else {
game.addEffect((ContinuousEffect) effect, source);
} else {
// Paying cost was cancels so try to undo payment so far
game.restoreState(bookmark, DoIfCostPaid.class.getName());
if (!otherwiseEffects.isEmpty()) {
for (Effect effect : otherwiseEffects) {
effect.setTargetPointer(this.targetPointer);
if (effect instanceof OneShotEffect) {
result &= effect.apply(game, source);
} else {
game.addEffect((ContinuousEffect) effect, source);
}
}
}
}

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
@ -50,21 +51,19 @@ public class FightTargetSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent originalPermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (originalPermanent != null) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
// only if target is legal the effect will be applied
if (source.getTargets().get(0).isLegal(source, game)) {
Permanent creature1 = game.getPermanent(source.getTargets().get(0).getFirstTarget());
// 20110930 - 701.10
if (creature1 != null && sourcePermanent != null) {
if (creature1.isCreature() && sourcePermanent.isCreature()) {
return sourcePermanent.fight(creature1, source, game);
}
MageObject sourceObject = source.getSourceObject(game);
if (sourceObject != null) {
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
Permanent creature1 = game.getPermanent(getTargetPointer().getFirst(game, source));
// 20110930 - 701.10
if (creature1 != null && sourcePermanent != null) {
if (creature1.isCreature() && sourcePermanent.isCreature()) {
return sourcePermanent.fight(creature1, source, game);
}
}
if (!game.isSimulation())
game.informPlayers(originalPermanent.getLogName() + ": Fighting effect has been fizzled.");
if (!game.isSimulation()) {
game.informPlayers(sourceObject.getLogName() + ": Fighting effect has been fizzled.");
}
}
return false;
}
@ -83,4 +82,3 @@ public class FightTargetSourceEffect extends OneShotEffect {
}
}

View file

@ -8,11 +8,9 @@ import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.players.Player;
/**
* @author Loki
*/
@ -33,14 +31,15 @@ public class FlipSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
Player controller = game.getPlayer(source.getControllerId());
if (permanent != null && controller != null) {
if (permanent.flip(game)) {
ContinuousEffect effect = new ConditionalContinuousEffect(new CopyTokenEffect(flipToken), FlippedCondition.instance, "");
game.addEffect(effect, source);
if (!game.isSimulation())
if (!game.isSimulation()) {
game.informPlayers(new StringBuilder(controller.getLogName()).append(" flips ").append(permanent.getName()).toString());
}
return true;
}
}

View file

@ -35,7 +35,6 @@ import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
@ -150,6 +149,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
FilterCard pickFilter, Zone targetZoneLookedCards, boolean putOnTop,
boolean reveal, boolean upTo, Zone targetZonePickedCards,
boolean optional) {
this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
targetZoneLookedCards, putOnTop, reveal, upTo,
targetZonePickedCards, optional, true, true);
@ -207,16 +207,10 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
}
@Override
protected void cardLooked(Card card, Game game, Ability source) {
if (numberToPick.calculate(game, source, this) > 0 && filter.match(card, game)) {
++foundCardsToPick;
}
}
@Override
protected void actionWithSelectedCards(Cards cards, Game game, Ability source, String windowName) {
protected void actionWithSelectedCards(Cards cards, Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null && foundCardsToPick > 0) {
if (player != null && numberToPick.calculate(game, source, this) > 0
&& cards.count(filter, source.getSourceId(), source.getControllerId(), game) > 0) {
if (!optional || player.chooseUse(Outcome.DrawCard, getMayText(), source, game)) {
FilterCard pickFilter = filter.copy();
pickFilter.setMessage(getPickText());
@ -231,7 +225,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
player.moveCards(pickedCards.getCards(game), targetPickedCards, source, game);
}
if (revealPickedCards) {
player.revealCards(windowName, pickedCards, game);
player.revealCards(source, pickedCards, game);
}
}
@ -346,7 +340,14 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
}
sb.append(" order");
} else if (targetZoneLookedCards == Zone.GRAVEYARD) {
sb.append(" and the other into your graveyard");
sb.append(" and the");
if (numberOfCards instanceof StaticValue && numberToPick instanceof StaticValue
&& ((StaticValue) numberToPick).getValue() + 1 == ((StaticValue) numberOfCards).getValue()) {
sb.append(" other");
} else {
sb.append(" rest");
}
sb.append(" into your graveyard");
}
}
// get text frame from super class and inject action text

View file

@ -29,18 +29,15 @@ package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.SpellAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
@ -105,46 +102,25 @@ public class LookLibraryControllerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
String windowName = "Reveal";
if (source instanceof SpellAbility) {
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null) {
windowName = sourceCard.getIdName();
}
} else {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
windowName = sourcePermanent.getIdName();
}
}
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
// take cards from library and look at them
boolean topCardRevealed = player.isTopCardRevealed();
player.setTopCardRevealed(false);
Cards cards = new CardsImpl();
int count = Math.min(player.getLibrary().size(), this.numberOfCards.calculate(game, source, this));
for (int i = 0; i < count; i++) {
Card card = player.getLibrary().removeFromTop(game);
if (card != null) {
cards.add(card);
this.cardLooked(card, game, source);
}
}
player.lookAtCards(windowName, cards, game);
boolean topCardRevealed = controller.isTopCardRevealed();
controller.setTopCardRevealed(false);
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, this.numberOfCards.calculate(game, source, this)));
this.actionWithSelectedCards(cards, game, source, windowName);
controller.lookAtCards(source, null, cards, game);
this.putCardsBack(source, player, cards, game);
this.actionWithSelectedCards(cards, game, source);
player.setTopCardRevealed(topCardRevealed);
this.putCardsBack(source, controller, cards, game);
this.mayShuffle(player, source, game);
controller.setTopCardRevealed(topCardRevealed);
this.mayShuffle(controller, source, game);
return true;
}
@ -158,10 +134,7 @@ public class LookLibraryControllerEffect extends OneShotEffect {
return this;
}
protected void cardLooked(Card card, Game game, Ability source) {
}
protected void actionWithSelectedCards(Cards cards, Game game, Ability source, String windowName) {
protected void actionWithSelectedCards(Cards cards, Game game, Ability source) {
}
/**

View file

@ -47,11 +47,13 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect {
protected int amount;
protected boolean putToGraveyard;
protected boolean mayShuffleAfter; // for Visions
public LookLibraryTopCardTargetPlayerEffect(int amount) {
super(Outcome.Benefit);
this.amount = amount;
this.putToGraveyard = false;
this.mayShuffleAfter = false;
setText();
}
@ -59,6 +61,15 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect {
super(Outcome.Benefit);
this.amount = amount;
this.putToGraveyard = putToGraveyard;
this.mayShuffleAfter = false;
setText();
}
public LookLibraryTopCardTargetPlayerEffect(int amount, boolean putToGraveyard, boolean mayShuffleAfter) {
super(Outcome.Benefit);
this.amount = amount;
this.putToGraveyard = putToGraveyard;
this.mayShuffleAfter = mayShuffleAfter;
setText();
}
@ -70,6 +81,7 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect {
super(effect);
amount = effect.amount;
putToGraveyard = effect.putToGraveyard;
mayShuffleAfter = effect.mayShuffleAfter;
}
@Override
@ -95,6 +107,11 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect {
}
}
}
if (mayShuffleAfter) {
if (player.chooseUse(Outcome.Benefit, (player == targetPlayer ? "Shuffle your library?" : "Do you want the chosen player to shuffle his or her library?"), source, game)) {
targetPlayer.shuffleLibrary(source, game);
}
}
return true;
}
return false;
@ -118,6 +135,9 @@ public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect {
}
sb.append(" into that player's graveyard");
}
if (mayShuffleAfter) {
sb.append(". You may then have that player shuffle that library");
}
this.staticText = sb.toString();
}
}

View file

@ -24,10 +24,11 @@
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
*/
package mage.abilities.effects.common;
import java.util.ArrayList;
import java.util.List;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
@ -45,26 +46,72 @@ import mage.game.events.ManaEvent;
*/
public abstract class ManaEffect extends OneShotEffect {
protected Mana createdMana;
public ManaEffect() {
super(Outcome.PutManaInPool);
createdMana = null;
}
public ManaEffect(final ManaEffect effect) {
super(effect);
this.createdMana = effect.createdMana == null ? null : effect.createdMana.copy();
}
public abstract Mana getMana(Game game, Ability source);
/**
* Creates the mana the effect can produce or if that already has happened
* returns the mana the effect has created during its process of resolving
*
* @param game
* @param source
* @return
*/
public Mana getMana(Game game, Ability source) {
if (createdMana == null) {
return createdMana = produceMana(false, game, source);
}
return createdMana;
}
/**
* Only used for mana effects that decide which kind of mana is produced during resolution of the effect.
*
* Returns the currently available max mana variations the effect can
* produce
*
* @param game
* @param source
* @return
*/
public List<Mana> getNetMana(Game game, Ability source) {
List<Mana> netMana = new ArrayList<>();
Mana mana = produceMana(true, game, source);
if (mana != null) {
netMana.add(mana);
}
return netMana;
}
/**
* Produced the mana the effect can produce
*
* @param netMana true - produce the hypotetical possible mana for check of
* possible castable spells
* @param game
* @param source
* @return
*/
public abstract Mana produceMana(boolean netMana, Game game, Ability source);
/**
* Only used for mana effects that decide which kind of mana is produced
* during resolution of the effect.
*
* @param mana
* @param game
* @param source
*/
public void checkToFirePossibleEvents(Mana mana, Game game, Ability source) {
if (source.getAbilityType()==AbilityType.MANA) {
for (Cost cost: source.getCosts()) {
if (source.getAbilityType() == AbilityType.MANA) {
for (Cost cost : source.getCosts()) {
if (cost instanceof TapSourceCost) {
ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, source.getSourceId(), source.getSourceId(), source.getControllerId(), mana);
if (!game.replaceEvent(event)) {

View file

@ -5,7 +5,6 @@
*/
package mage.abilities.effects.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
@ -34,9 +33,8 @@ public class PhaseOutSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
if (sourceObject instanceof Permanent) {
Permanent permanent = (Permanent) sourceObject;
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent != null) {
return permanent.phaseOut(game);
}
return false;

View file

@ -54,6 +54,17 @@ public class PreventDamageToSourceEffect extends PreventionEffectImpl {
return new PreventDamageToSourceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game); //To change body of generated methods, choose Tools | Templates.
if (duration.isOnlyValidIfNoZoneChange()) {
// If source permanent is no longer onto battlefield discard the effect
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
}
}
}
@Override
public boolean apply(Game game, Ability source) {
return true;

View file

@ -18,8 +18,8 @@ import mage.game.permanent.Permanent;
*/
public class RedirectDamageFromSourceToTargetEffect extends RedirectionEffect {
public RedirectDamageFromSourceToTargetEffect(Duration duration, int amountToRedirect, boolean oneUsage) {
super(duration, amountToRedirect, oneUsage);
public RedirectDamageFromSourceToTargetEffect(Duration duration, int amountToRedirect, UsageType usageType) {
super(duration, amountToRedirect, usageType);
staticText = "The next " + amountToRedirect + " damage that would be dealt to {this} this turn is dealt to target creature you control instead.";
}

View file

@ -28,12 +28,18 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
@ -43,21 +49,25 @@ public class ReturnSourceFromGraveyardToBattlefieldEffect extends OneShotEffect
private boolean tapped;
private boolean ownerControl;
private boolean haste;
public ReturnSourceFromGraveyardToBattlefieldEffect() {
this(false);
}
public ReturnSourceFromGraveyardToBattlefieldEffect(boolean tapped) {
super(Outcome.PutCreatureInPlay);
this.tapped = tapped;
setText();
this(tapped, true);
}
public ReturnSourceFromGraveyardToBattlefieldEffect(boolean tapped, boolean ownerControl) {
this(tapped, ownerControl, false);
}
public ReturnSourceFromGraveyardToBattlefieldEffect(boolean tapped, boolean ownerControl, boolean haste) {
super(Outcome.PutCreatureInPlay);
this.tapped = tapped;
this.ownerControl = ownerControl;
this.haste = haste;
setText();
}
@ -65,6 +75,7 @@ public class ReturnSourceFromGraveyardToBattlefieldEffect extends OneShotEffect
super(effect);
this.tapped = effect.tapped;
this.ownerControl = effect.ownerControl;
this.haste = effect.haste;
}
@Override
@ -89,6 +100,14 @@ public class ReturnSourceFromGraveyardToBattlefieldEffect extends OneShotEffect
}
if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
player.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, true, null);
if (haste) {
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
}
}
}
return true;
}

View file

@ -33,6 +33,7 @@ import mage.cards.Card;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
*
@ -81,16 +82,17 @@ public class ReturnToBattlefieldUnderOwnerControlSourceEffect extends OneShotEff
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Card card = game.getCard(source.getSourceId());
if (card != null) {
if (controller != null && card != null) {
// return only from public zones
switch (game.getState().getZone(card.getId())) {
case EXILED:
case COMMAND:
case GRAVEYARD:
if (zoneChangeCounter < 0 || game.getState().getZoneChangeCounter(card.getId()) == zoneChangeCounter) {
Zone currentZone = game.getState().getZone(card.getId());
if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), card.getOwnerId(), tapped)) {
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, true, null)) {
if (attacking) {
game.getCombat().addAttackingCreature(card.getId(), game);
}

View file

@ -103,7 +103,7 @@ public class ReturnToHandTargetEffect extends OneShotEffect {
}
}
for (UUID copyId : copyIds) {
game.getStack().remove(game.getSpell(copyId));
game.getStack().remove(game.getSpell(copyId), game);
}
return controller.moveCards(cards, Zone.HAND, source, game);
}

View file

@ -63,10 +63,7 @@ public class TapSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
permanent = game.getPermanentEntering(source.getSourceId());
}
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent != null) {
if (withoutTrigger) {
permanent.setTapped(true);

View file

@ -31,8 +31,6 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
@ -46,6 +44,11 @@ import mage.util.CardUtil;
*/
public class UntapLandsEffect extends OneShotEffect {
private static final FilterLandPermanent filter = new FilterLandPermanent("untapped lands");
static {
filter.add(new TappedPredicate());
}
private final int amount;
private final boolean upTo;
@ -70,15 +73,12 @@ public class UntapLandsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
TargetLandPermanent target = new TargetLandPermanent(upTo ? 0 : amount, amount, StaticFilters.FILTER_LAND, true);
int tappedLands = game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game).size();
TargetLandPermanent target = new TargetLandPermanent(upTo ? 0 : Math.min(tappedLands, amount), amount, filter, true);
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
// UI Shortcut: Check if any lands are already tapped. If there are equal/fewer than amount, give the option to add those in to be untapped now.
FilterPermanent filter = new FilterLandPermanent();
filter.add(new TappedPredicate());
int tappedLands = game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game).size();
if (tappedLands <= amount) {
if (tappedLands <= amount && upTo) {
if (controller.chooseUse(outcome, "Include your tapped lands to untap?", source, game)) {
for (Permanent land : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
target.addTarget(land.getId(), source, game);

View file

@ -58,7 +58,7 @@ public class CantBeBlockedByAllSourceEffect extends RestrictionEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return source.getSourceId().equals(permanent.getId());
return permanent.equals(source.getSourcePermanentIfItStillExists(game));
}
@Override

View file

@ -38,13 +38,33 @@ import mage.game.permanent.Permanent;
*/
public class BecomesBlackZombieAdditionEffect extends ContinuousEffectImpl {
private boolean giveBlackColor = true;
public BecomesBlackZombieAdditionEffect() {
super(Duration.Custom, Outcome.Neutral);
staticText = "That creature is a black Zombie in addition to its other colors and types";
this.giveBlackColor = true;
updateText();
}
public BecomesBlackZombieAdditionEffect(boolean giveBlackColor) {
this();
this.giveBlackColor = giveBlackColor;
updateText();
}
public BecomesBlackZombieAdditionEffect(final BecomesBlackZombieAdditionEffect effect) {
super(effect);
this.giveBlackColor = effect.giveBlackColor;
updateText();
}
private void updateText() {
if (this.giveBlackColor) {
this.staticText = "That creature is a black Zombie in addition to its other colors and types";
} else {
this.staticText = "That creature is a Zombie in addition to its other types";
}
}
@Override
@ -73,7 +93,7 @@ public class BecomesBlackZombieAdditionEffect extends ContinuousEffectImpl {
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (sublayer == SubLayer.NA && this.giveBlackColor) {
creature.getColor(game).setBlack(true);
}
break;

View file

@ -52,21 +52,24 @@ import java.util.Set;
public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
protected Token token;
protected String type;
protected String theyAreStillType;
private final FilterPermanent filter;
private boolean loseColor = true;
public BecomesCreatureAllEffect(Token token, String type, FilterPermanent filter, Duration duration) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor) {
super(duration, Outcome.BecomeCreature);
this.token = token;
this.type = type;
this.theyAreStillType = theyAreStillType;
this.filter = filter;
this.loseColor = loseColor;
}
public BecomesCreatureAllEffect(final BecomesCreatureAllEffect effect) {
super(effect);
token = effect.token.copy();
type = effect.type;
this.token = effect.token.copy();
this.theyAreStillType = effect.theyAreStillType;
this.filter = effect.filter.copy();
this.loseColor = effect.loseColor;
}
@Override
@ -94,6 +97,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
} else {
affectedPermanents = new HashSet<>(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
}
for(Permanent permanent : affectedPermanents) {
if (permanent != null) {
switch (layer) {
@ -106,7 +110,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
}
}
}
if (type == null) {
if (theyAreStillType == null) {
permanent.getSubtype(game).clear();
}
if (!token.getSubtype(game).isEmpty()) {
@ -114,13 +118,22 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
}
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (this.loseColor) {
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setGreen(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setWhite(false);
permanent.getColor(game).setRed(false);
}
if (token.getColor(game).hasColor()) {
permanent.getColor(game).setColor(token.getColor(game));
permanent.getColor(game).addColor(token.getColor(game));
}
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
if (!token.getAbilities().isEmpty()) {
@ -130,6 +143,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int power = token.getPower().getValue();
@ -139,6 +153,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
permanent.getToughness().setValue(toughness);
}
}
break;
}
}
}
@ -168,8 +183,8 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
sb.append(" become ");
}
sb.append(token.getDescription());
if (type != null && !type.isEmpty()) {
sb.append(". They're still ").append(type);
if (theyAreStillType != null && !theyAreStillType.isEmpty()) {
sb.append(". They're still ").append(theyAreStillType);
}
return sb.toString();
}

View file

@ -40,7 +40,7 @@ import mage.game.permanent.token.Token;
public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
public enum LoseType {
NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE_AND_PT, ABILITIES_AND_PT
NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE, COLOR
}
protected Token token;
@ -98,7 +98,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
switch (loseType) {
case ALL:
case ALL_BUT_COLOR:
case ABILITIES_SUBTYPE_AND_PT:
case ABILITIES_SUBTYPE:
permanent.getSubtype(game).retainAll(SubType.getLandTypes(false));
break;
}
@ -107,12 +107,12 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
permanent.getSubtype(game).add(t);
}
}
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (loseType == LoseType.ALL) {
if (loseType == LoseType.ALL || loseType == LoseType.COLOR) {
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setGreen(false);
permanent.getColor(game).setBlue(false);
@ -124,29 +124,29 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
}
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
switch (loseType) {
case ALL:
case ALL_BUT_COLOR:
case ABILITIES:
case ABILITIES_AND_PT:
case ABILITIES_SUBTYPE_AND_PT:
case ABILITIES_SUBTYPE:
permanent.removeAllAbilities(source.getSourceId(), game);
break;
}
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
permanent.getPower().setValue(token.getPower().getValue());
permanent.getToughness().setValue(token.getToughness().getValue());
break;
}
break;
}
}
return true;

View file

@ -31,10 +31,10 @@ import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
/**
@ -43,34 +43,36 @@ import mage.game.permanent.token.Token;
public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements SourceEffect {
protected Token token;
protected String type;
protected String theyAreStillType;
protected boolean losePreviousTypes;
protected DynamicValue power = null;
protected DynamicValue toughness = null;
public BecomesCreatureSourceEffect(Token token, String type, Duration duration) {
this(token, type, duration, false, false);
public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration) {
this(token, theyAreStillType, duration, false, false);
}
public BecomesCreatureSourceEffect(Token token, String type, Duration duration, boolean losePreviousTypes, boolean characterDefining) {
this(token, type, duration, losePreviousTypes, characterDefining, null, null);
public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration, boolean losePreviousTypes, boolean characterDefining) {
this(token, theyAreStillType, duration, losePreviousTypes, characterDefining, null, null);
}
public BecomesCreatureSourceEffect(Token token, String type, Duration duration, boolean losePreviousTypes, boolean characterDefining, DynamicValue power, DynamicValue toughness) {
public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration, boolean losePreviousTypes, boolean characterDefining, DynamicValue power, DynamicValue toughness) {
super(duration, Outcome.BecomeCreature);
this.characterDefining = characterDefining;
this.token = token;
this.type = type;
this.theyAreStillType = theyAreStillType;
this.losePreviousTypes = losePreviousTypes;
this.power = power;
this.toughness = toughness;
setText();
this.addDependencyType(DependencyType.BecomeCreature);
}
public BecomesCreatureSourceEffect(final BecomesCreatureSourceEffect effect) {
super(effect);
this.token = effect.token.copy();
this.type = effect.type;
this.theyAreStillType = effect.theyAreStillType;
this.losePreviousTypes = effect.losePreviousTypes;
if (effect.power != null) {
this.power = effect.power.copy();
@ -108,10 +110,11 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
if (losePreviousTypes) {
permanent.getCardType().clear();
}
for (CardType t : token.getCardType()) {
permanent.addCardType(t);
for (CardType cardType : token.getCardType()) {
permanent.addCardType(cardType);
}
if (type != null && type.isEmpty() || type == null && permanent.isLand()) {
if (theyAreStillType != null && theyAreStillType.isEmpty() || theyAreStillType == null && permanent.isLand()) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes(false));
}
if (!token.getSubtype(game).isEmpty()) {
@ -120,6 +123,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
permanent.setIsAllCreatureTypes(token.isAllCreatureTypes());
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (token.getColor(game).hasColor()) {
@ -127,19 +131,20 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
}
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
break;
case PTChangingEffects_7:
if ((sublayer == SubLayer.CharacteristicDefining_7a && isCharacterDefining())
|| (sublayer == SubLayer.SetPT_7b && !isCharacterDefining())) {
if (power != null) {
permanent.getPower().setValue(power.calculate(game, source, this));
permanent.getPower().setValue(power.calculate(game, source, this)); // check all other becomes to use calculate?
} else if (token.getPower() != null) {
permanent.getPower().setValue(token.getPower().getValue());
}
@ -149,11 +154,15 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
permanent.getToughness().setValue(token.getToughness().getValue());
}
}
break;
}
return true;
} else if (duration == Duration.Custom) {
this.discard();
}
return false;
}
@ -163,8 +172,8 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
}
private void setText() {
if (type != null && !type.isEmpty()) {
staticText = duration.toString() + " {this} becomes a " + token.getDescription() + " that's still a " + this.type;
if (theyAreStillType != null && !theyAreStillType.isEmpty()) {
staticText = duration.toString() + " {this} becomes a " + token.getDescription() + " that's still a " + this.theyAreStillType;
} else {
staticText = duration.toString() + " {this} becomes a " + token.getDescription();
}

View file

@ -39,6 +39,9 @@ import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -50,6 +53,7 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
private String rule;
private boolean withSource;
private boolean withSecondTarget;
private boolean destroyAttachedAuras;
private Map<UUID, Integer> zoneChangeCounter = new HashMap<>();
private Map<UUID, UUID> lockedControllers = new HashMap<>();
@ -62,9 +66,14 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
}
public ExchangeControlTargetEffect(Duration duration, String rule, boolean withSource, boolean withSecondTarget) {
this(duration, rule, withSource, withSecondTarget, false);
}
public ExchangeControlTargetEffect(Duration duration, String rule, boolean withSource, boolean withSecondTarget, boolean destroyAttachedAuras) {
super(duration, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
this.withSource = withSource;
this.withSecondTarget = withSecondTarget;
this.destroyAttachedAuras = destroyAttachedAuras;
this.rule = rule;
}
@ -73,6 +82,7 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
this.rule = effect.rule;
this.withSource = effect.withSource;
this.withSecondTarget = effect.withSecondTarget;
this.destroyAttachedAuras = effect.destroyAttachedAuras;
this.lockedControllers = new HashMap<>(effect.lockedControllers);
this.zoneChangeCounter = new HashMap<>(effect.zoneChangeCounter);
}
@ -141,6 +151,16 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
}
permanent.changeControllerId(lockedControllers.get(permanent.getId()), game);
permanent.getAbilities().setControllerId(lockedControllers.get(permanent.getId()));
if (destroyAttachedAuras) {
FilterPermanent filter = new FilterPermanent();
filter.add(new SubtypePredicate(SubType.AURA));
for (UUID attachmentId : new HashSet<>(permanent.getAttachments())) {
Permanent attachment = game.getPermanent(attachmentId);
if (attachment != null && filter.match(attachment, game)) {
attachment.destroy(source.getSourceId(), game, false);
}
}
}
}
if (!toDelete.isEmpty()) {
for (UUID uuid : toDelete) {

View file

@ -92,6 +92,13 @@ public class GainAbilitySourceEffect extends ContinuousEffectImpl implements Sou
@Override
public void init(Ability source, Game game) {
super.init(source, game);
if (!onCard && Duration.WhileOnBattlefield != duration) {
// If source permanent is no longer onto battlefield discard the effect
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
return;
}
}
if (affectedObjectsSet) {
Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (permanent != null) {

View file

@ -12,38 +12,50 @@ import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author Noahsark
*/
public class LoseAbilitySourceEffect extends ContinuousEffectImpl{
public class LoseAbilitySourceEffect extends ContinuousEffectImpl {
protected Ability ability;
public LoseAbilitySourceEffect(Ability ability){
public LoseAbilitySourceEffect(Ability ability) {
this(ability, Duration.WhileOnBattlefield);
}
public LoseAbilitySourceEffect(Ability ability, Duration duration){
public LoseAbilitySourceEffect(Ability ability, Duration duration) {
super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility);
this.ability = ability;
staticText = "{this} loses " + ability.getRule() + ' ' + duration.toString();
}
public LoseAbilitySourceEffect(final LoseAbilitySourceEffect effect){
public LoseAbilitySourceEffect(final LoseAbilitySourceEffect effect) {
super(effect);
this.ability = effect.ability.copy();
}
@Override
public LoseAbilitySourceEffect copy(){
public LoseAbilitySourceEffect copy() {
return new LoseAbilitySourceEffect(this);
}
@Override
public boolean apply(Game game, Ability source){
public void init(Ability source, Game game) {
super.init(source, game); //To change body of generated methods, choose Tools | Templates.
if (duration.isOnlyValidIfNoZoneChange()) {
// If source permanent is no longer onto battlefield discard the effect
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
}
}
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null){
if (permanent != null) {
// 112.10
while (permanent.getAbilities().remove(ability)) {

View file

@ -69,6 +69,17 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement
return new LoseCreatureTypeSourceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game); //To change body of generated methods, choose Tools | Templates.
if (duration.isOnlyValidIfNoZoneChange()) {
// If source permanent is no longer onto battlefield discard the effect
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
}
}
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
if (dynamicValue.calculate(game, source, this) >= lessThan) {

View file

@ -1,16 +1,16 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,19 +20,19 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -55,14 +55,29 @@ public class SwitchPowerToughnessSourceEffect extends ContinuousEffectImpl {
return new SwitchPowerToughnessSourceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game); //To change body of generated methods, choose Tools | Templates.
if (duration.isOnlyValidIfNoZoneChange()) {
// If source permanent is no longer onto battlefield discard the effect
if (source.getSourcePermanentIfItStillExists(game) == null) {
discard();
}
}
}
@Override
public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(source.getSourceId());
if (target != null) {
int power = target.getPower().getValue();
target.getPower().setValue(target.getToughness().getValue());
target.getToughness().setValue(power);
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
if (sourcePermanent != null) {
int power = sourcePermanent.getPower().getValue();
sourcePermanent.getPower().setValue(sourcePermanent.getToughness().getValue());
sourcePermanent.getToughness().setValue(power);
return true;
} else {
if (duration.isOnlyValidIfNoZoneChange()) {
discard();
}
}
return false;
}

View file

@ -53,6 +53,7 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
private FilterCard filter;
private int amount;
private final boolean upTo;
private boolean onlyControlled;
public SpellsCostReductionAllEffect(int amount) {
this(new FilterCard("Spells"), amount);
@ -63,19 +64,24 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
}
public SpellsCostReductionAllEffect(FilterCard filter, int amount, boolean upTo) {
this(filter, amount, upTo, false);
}
public SpellsCostReductionAllEffect(FilterCard filter, int amount, boolean upTo, boolean onlyControlled) {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = filter;
this.amount = amount;
this.upTo = upTo;
this.onlyControlled = onlyControlled;
this.staticText = filter.getMessage() + " cost " + (upTo ? "up to " : "") + '{' + amount + "} less to cast";
}
protected SpellsCostReductionAllEffect(SpellsCostReductionAllEffect effect) {
protected SpellsCostReductionAllEffect(final SpellsCostReductionAllEffect effect) {
super(effect);
this.filter = effect.filter;
this.amount = effect.amount;
this.upTo = effect.upTo;
this.onlyControlled = effect.onlyControlled;
}
@Override
@ -136,6 +142,9 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (onlyControlled && abilityToModify.getControllerId().equals(source.getControllerId())) {
return false;
}
if (abilityToModify instanceof SpellAbility) {
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId());
if (spell != null) {

View file

@ -19,7 +19,11 @@ import mage.game.Game;
public class SpellsCostReductionAllOfChosenSubtypeEffect extends SpellsCostReductionAllEffect {
public SpellsCostReductionAllOfChosenSubtypeEffect(FilterCard filter, int amount) {
super(filter, amount);
this(filter, amount, false);
}
public SpellsCostReductionAllOfChosenSubtypeEffect(FilterCard filter, int amount, boolean onlyControlled) {
super(filter, amount, false, onlyControlled);
}
public SpellsCostReductionAllOfChosenSubtypeEffect(final SpellsCostReductionAllOfChosenSubtypeEffect effect) {

View file

@ -39,7 +39,7 @@ import mage.game.permanent.Permanent;
* @author TheElk801
*/
public class RemoveAllCountersSourceEffect extends OneShotEffect {
private final CounterType counterType;
public RemoveAllCountersSourceEffect(CounterType counterType) {
@ -55,13 +55,13 @@ public class RemoveAllCountersSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if(permanent != null) {
int count = permanent.getCounters(game).getCount(counterType);
permanent.removeCounters(counterType.getName(), count, game);
return true;
}
return false;
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent != null) {
int count = permanent.getCounters(game).getCount(counterType);
permanent.removeCounters(counterType.getName(), count, game);
return true;
}
return false;
}
@Override

View file

@ -56,7 +56,7 @@ public class RemoveCounterSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent != null) {
int toRemove = Math.min(counter.getCount(), permanent.getCounters(game).getCount(counter.getName()));
if (toRemove > 0) {
@ -67,18 +67,20 @@ public class RemoveCounterSourceEffect extends OneShotEffect {
}
return true;
}
Card card = game.getCard(source.getSourceId());
if (card != null) {
int toRemove = Math.min(counter.getCount(), card.getCounters(game).getCount(counter.getName()));
if (toRemove > 0) {
card.removeCounters(counter.getName(), toRemove, game);
if (!game.isSimulation()) {
game.informPlayers("Removed " + toRemove + ' ' + counter.getName()
+ " counter from " + card.getLogName()
+ " (" + card.getCounters(game).getCount(counter.getName()) + " left)");
if (!(source.getSourceObject(game) instanceof Permanent)) {
Card card = game.getCard(source.getSourceId());
if (card != null) {
int toRemove = Math.min(counter.getCount(), card.getCounters(game).getCount(counter.getName()));
if (toRemove > 0) {
card.removeCounters(counter.getName(), toRemove, game);
if (!game.isSimulation()) {
game.informPlayers("Removed " + toRemove + ' ' + counter.getName()
+ " counter from " + card.getLogName()
+ " (" + card.getCounters(game).getCount(counter.getName()) + " left)");
}
}
return true;
}
return true;
}
return false;
}

View file

@ -53,7 +53,7 @@ public class SweepEffect extends OneShotEffect {
public SweepEffect(SubType sweepSubtype) {
super(Outcome.Benefit);
this.sweepSubtype = sweepSubtype;
this.staticText = "<i>Sweep</i> - Return any number of " + sweepSubtype + (sweepSubtype.getDescription().endsWith("s") ? "" : "s") + " you control to their owner's hand";
this.staticText = "<i>Sweep</i> &mdash; Return any number of " + sweepSubtype + (sweepSubtype.getDescription().endsWith("s") ? "" : "s") + " you control to their owner's hand";
}
public SweepEffect(final SweepEffect effect) {

View file

@ -0,0 +1,29 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.mana.builder.ConditionalManaBuilder;
/**
*
* @author LevelX2
*/
public class AddConditionalColorlessManaEffect extends AddConditionalManaEffect {
public AddConditionalColorlessManaEffect(int amount, ConditionalManaBuilder manaBuilder) {
super(Mana.ColorlessMana(amount), manaBuilder);
}
public AddConditionalColorlessManaEffect(final AddConditionalColorlessManaEffect effect) {
super(effect);
}
@Override
public AddConditionalColorlessManaEffect copy() {
return new AddConditionalColorlessManaEffect(this);
}
}

View file

@ -3,10 +3,11 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.game.Game;
import mage.players.Player;
@ -49,7 +50,11 @@ public class AddConditionalManaEffect extends ManaEffect {
}
@Override
public Mana getMana(Game game, Ability source) {
public Mana produceMana(boolean netMana, Game game, Ability source) {
return manaBuilder.setMana(mana, source, game).build();
}
public Mana getMana() {
return mana;
}
}

View file

@ -25,12 +25,14 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.ConditionalMana;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.choices.ChoiceColor;
import mage.game.Game;
@ -63,9 +65,9 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
staticText = "Add "
+ (amount instanceof StaticValue ? (CardUtil.numberToText(((StaticValue) amount).toString())) : "")
+ " mana "
+ (oneChoice ? "of any"
+ (amount instanceof StaticValue && (((StaticValue) amount).toString()).equals("1") ? "" : " one")
+ " color" : "in any combination of colors")
+ (oneChoice || (amount instanceof StaticValue && (((StaticValue) amount).toString()).equals("1"))
? "of any" + (amount instanceof StaticValue && (((StaticValue) amount).toString()).equals("1") ? "" : " one") + " color"
: "in any combination of colors")
+ ". " + manaBuilder.getRule();
}
@ -84,39 +86,44 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
if (controller != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
controller.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return null;
}
ConditionalMana mana = null;
int value = amount.calculate(game, source, this);
boolean result = false;
ChoiceColor choice = new ChoiceColor(true);
for (int i = 0; i < value; i++) {
controller.choose(outcome, choice, game);
if (choice.getChoice() == null) {
return false;
controller.choose(outcome, choice, game);
}
Mana mana = choice.getMana(1);
if (mana != null) {
mana = manaBuilder.setMana(mana, source, game).build();
if (choice.getChoice() == null) {
return null;
}
if (mana != null) {
checkToFirePossibleEvents(mana, game, source);
controller.getManaPool().addMana(mana, game, source);
result = true;
}
if (!oneChoice) {
if (oneChoice) {
mana = new ConditionalMana(manaBuilder.setMana(choice.getMana(value), source, game).build());
break;
} else {
if (mana == null) {
mana = new ConditionalMana(manaBuilder.setMana(choice.getMana(1), source, game).build());
} else {
mana.add(choice.getMana(1));
}
choice.clearChoice();
}
}
return result;
}
return mana;
@Override
public Mana getMana(Game game, Ability source) {
//TODO: TAP_FOR_MANA Event does not support currently to get an amount > 1 of conditional mana
return null;
}
}

View file

@ -25,10 +25,13 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import java.util.ArrayList;
import java.util.List;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.effects.common.ManaEffect;
import mage.choices.ChoiceColor;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -53,14 +56,12 @@ public class AddManaAnyColorAttachedControllerEffect extends ManaEffect {
public boolean apply(Game game, Ability source) {
Permanent enchantment = game.getPermanent(source.getSourceId());
if (enchantment != null) {
Permanent land = game.getPermanent(enchantment.getAttachedTo());
if (land != null) {
Player player = game.getPlayer(land.getControllerId());
ChoiceColor choice = new ChoiceColor();
if (player != null && player.choose(outcome, choice, game)) {
Mana mana = choice.getMana(1);
checkToFirePossibleEvents(mana, game, source);
player.getManaPool().addMana(mana, game, source);
Permanent permanentattachedTo = game.getPermanent(enchantment.getAttachedTo());
if (permanentattachedTo != null) {
Player player = game.getPlayer(permanentattachedTo.getControllerId());
if (player != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
player.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
}
@ -74,8 +75,30 @@ public class AddManaAnyColorAttachedControllerEffect extends ManaEffect {
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
public Mana produceMana(boolean netMana, Game game, Ability source) {
Permanent enchantment = game.getPermanent(source.getSourceId());
if (enchantment != null) {
Permanent land = game.getPermanent(enchantment.getAttachedTo());
if (land != null) {
Player player = game.getPlayer(land.getControllerId());
ChoiceColor choice = new ChoiceColor();
if (player != null && player.choose(outcome, choice, game)) {
return choice.getMana(1);
}
}
}
return new Mana();
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
ArrayList<Mana> netMana = new ArrayList<>();
netMana.add(Mana.GreenMana(1));
netMana.add(Mana.WhiteMana(1));
netMana.add(Mana.BlueMana(1));
netMana.add(Mana.RedMana(1));
netMana.add(Mana.BlackMana(1));
return netMana;
}
}

View file

@ -0,0 +1,54 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.mana;
import mage.Mana;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.effects.common.ManaEffect;
import mage.constants.ColoredManaSymbol;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class AddManaChosenColorEffect extends ManaEffect {
public AddManaChosenColorEffect() {
super();
staticText = "Add one mana of the chosen color";
}
public AddManaChosenColorEffect(final AddManaChosenColorEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.getManaPool().addMana(getMana(game, source), game, source);
}
return true;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color");
if (color != null) {
return new Mana(ColoredManaSymbol.lookup(color.toString().charAt(0)));
} else {
return null;
}
}
@Override
public AddManaChosenColorEffect copy() {
return new AddManaChosenColorEffect(this);
}
}

View file

@ -25,14 +25,16 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.ManaEffect;
import mage.constants.ColoredManaSymbol;
import mage.game.Game;
import mage.players.Player;
@ -90,6 +92,17 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
player.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
Mana mana = new Mana();
@ -111,16 +124,17 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
}
}
}
checkToFirePossibleEvents(mana, game, source);
player.getManaPool().addMana(mana, game, source);
return true;
return mana;
}
return false;
return null;
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
public List<Mana> getNetMana(Game game, Ability source) {
ArrayList<Mana> netMana = new ArrayList<>();
netMana.add(new Mana(0, 0, 0, 0, 0, 0, amount.calculate(game, source, this), 0));
return netMana;
}
private String setText() {

View file

@ -25,7 +25,7 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.Ability;
@ -91,7 +91,7 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
}
@Override
public Mana getMana() {
public Mana getManaTemplate() {
return new Mana(0, 0, 0, 0, 0, 0, amount, 0);
}

View file

@ -25,10 +25,11 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.effects.common.ManaEffect;
import mage.choices.Choice;
import mage.choices.ChoiceColor;
import mage.game.Game;
@ -58,6 +59,24 @@ public class AddManaOfAnyTypeProducedEffect extends ManaEffect {
if (targetController == null) {
return false;
}
checkToFirePossibleEvents(getMana(game, source), game, source);
targetController.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
if (netMana) {
return null;
}
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
Player targetController = game.getPlayer(permanent.getControllerId());
if (targetController == null) {
return null;
}
Mana types = (Mana) this.getValue("mana");
Choice choice = new ChoiceColor(true);
choice.getChoices().clear();
@ -80,15 +99,16 @@ public class AddManaOfAnyTypeProducedEffect extends ManaEffect {
if (types.getColorless() > 0) {
choice.getChoices().add("Colorless");
}
Mana newMana = new Mana();
if (!choice.getChoices().isEmpty()) {
if (choice.getChoices().size() == 1) {
choice.setChoice(choice.getChoices().iterator().next());
} else {
if (!targetController.choose(outcome, choice, game)) {
return false;
return null;
}
}
Mana newMana = new Mana();
switch (choice.getChoice()) {
case "Black":
newMana.setBlack(1);
@ -109,13 +129,10 @@ public class AddManaOfAnyTypeProducedEffect extends ManaEffect {
newMana.setColorless(1);
break;
}
checkToFirePossibleEvents(newMana, game, source);
targetController.getManaPool().addMana(newMana, game, source);
}
return true;
return newMana;
}
return false;
return null;
}
@Override
@ -123,8 +140,4 @@ public class AddManaOfAnyTypeProducedEffect extends ManaEffect {
return new AddManaOfAnyTypeProducedEffect(this);
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
}
}

View file

@ -4,7 +4,7 @@
* and open the template in the editor.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.Ability;

View file

@ -3,11 +3,11 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.effects.common.ManaEffect;
import mage.game.Game;
import mage.players.Player;
@ -15,28 +15,30 @@ import mage.players.Player;
*
* @author LevelX2
*/
public class AddManaToManaPoolTargetControllerEffect extends ManaEffect {
protected Mana mana;
protected boolean emptyOnlyOnTurnsEnd;
public AddManaToManaPoolTargetControllerEffect(Mana mana, String textManaPoolOwner) {
this(mana, textManaPoolOwner, false);
}
/**
* Adds mana to the mana pool of target pointer player
*
*
* @param mana mana that will be added to the pool
* @param textManaPoolOwner text that references to the mana pool owner (e.g. "damaged player's")
* @param emptyOnTurnsEnd if set, the mana will empty only on end of turnstep
*
*/
* @param textManaPoolOwner text that references to the mana pool owner
* (e.g. "damaged player's")
* @param emptyOnTurnsEnd if set, the mana will empty only on end of
* turnstep
*
*/
public AddManaToManaPoolTargetControllerEffect(Mana mana, String textManaPoolOwner, boolean emptyOnTurnsEnd) {
super();
this.mana = mana;
this.emptyOnlyOnTurnsEnd = emptyOnTurnsEnd;
this.staticText = (textManaPoolOwner.equals("their")?"that player adds ":"add ") + mana.toString() + " to " + textManaPoolOwner + " mana pool";
this.staticText = (textManaPoolOwner.equals("their") ? "that player adds " : "add ") + mana.toString() + " to " + textManaPoolOwner + " mana pool";
}
public AddManaToManaPoolTargetControllerEffect(final AddManaToManaPoolTargetControllerEffect effect) {
@ -54,15 +56,17 @@ public class AddManaToManaPoolTargetControllerEffect extends ManaEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
if (player != null) {
player.getManaPool().addMana(mana, game, source, emptyOnlyOnTurnsEnd);
player.getManaPool().addMana(getMana(game, source), game, source, emptyOnlyOnTurnsEnd);
return true;
}
return false;
}
@Override
public Mana getMana(Game game, Ability source) {
return mana;
public Mana produceMana(boolean netMana, Game game, Ability source) {
if (netMana) {
return null;
}
return mana.copy();
}
}

View file

@ -1,29 +1,31 @@
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.ConditionalMana;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.effects.common.ManaEffect;
import mage.game.Game;
public class BasicManaEffect extends ManaEffect {
protected Mana mana;
protected Mana manaTemplate;
public BasicManaEffect(Mana mana) {
super();
this.mana = mana;
this.manaTemplate = mana;
staticText = "add " + mana.toString();
}
public BasicManaEffect(ConditionalMana conditionalMana) {
super();
this.mana = conditionalMana;
staticText = "add " + mana.toString() + " " + conditionalMana.getDescription();
this.manaTemplate = conditionalMana;
staticText = "add " + manaTemplate.toString() + " " + conditionalMana.getDescription();
}
public BasicManaEffect(final BasicManaEffect effect) {
super(effect);
this.mana = effect.mana.copy();
this.manaTemplate = effect.manaTemplate.copy();
}
@Override
@ -33,16 +35,17 @@ public class BasicManaEffect extends ManaEffect {
@Override
public boolean apply(Game game, Ability source) {
game.getPlayer(source.getControllerId()).getManaPool().addMana(mana, game, source);
game.getPlayer(source.getControllerId()).getManaPool().addMana(getMana(game, source), game, source);
return true;
}
public Mana getMana() {
return mana;
public Mana getManaTemplate() {
return manaTemplate;
}
@Override
public Mana getMana(Game game, Ability source) {
return mana;
public Mana produceMana(boolean netMana, Game game, Ability source) {
return manaTemplate.copy();
}
}

View file

@ -3,14 +3,17 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.costs.Cost;
import mage.abilities.effects.common.ManaEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
@ -69,6 +72,24 @@ public class DoUnlessAnyPlayerPaysManaEffect extends ManaEffect {
return false;
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
if (cost.canPay(source, source.getSourceId(), source.getControllerId(), game)) {
return manaEffect.getNetMana(game, source);
}
return new ArrayList<>();
}
@Override
public Mana getMana(Game game, Ability source) {
return manaEffect.getMana(game, source);
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
return manaEffect.produceMana(netMana, game, source);
}
protected Player getPayingPlayer(Game game, Ability source) {
return game.getPlayer(source.getControllerId());
}
@ -81,11 +102,6 @@ public class DoUnlessAnyPlayerPaysManaEffect extends ManaEffect {
return manaEffect.getText(mode) + " unless any player pays " + cost.getText();
}
@Override
public Mana getMana(Game game, Ability source) {
return manaEffect.getMana(game, source);
}
@Override
public ManaEffect copy() {
return new DoUnlessAnyPlayerPaysManaEffect(this);

View file

@ -25,7 +25,7 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.effects.common;
package mage.abilities.effects.mana;
import mage.Mana;
import mage.abilities.Ability;
@ -64,10 +64,10 @@ public class DynamicManaEffect extends BasicManaEffect {
* @param mana
* @param amount
* @param text
* @param oneChoice is all mana from the same colour or if false the player
* can choose different colours
* @param oneChoice is all manaTemplate from the same colour or if false the
* player can choose different colours
* @param netAmount a dynamic value that calculates the possible available
* mana (e.g. if you have to pay by removing counters from source)
* manaTemplate (e.g. if you have to pay by removing counters from source)
*/
public DynamicManaEffect(Mana mana, DynamicValue amount, String text, boolean oneChoice, DynamicValue netAmount) {
super(mana);
@ -96,9 +96,8 @@ public class DynamicManaEffect extends BasicManaEffect {
@Override
public boolean apply(Game game, Ability source) {
Mana computedMana = computeMana(false, game, source);
checkToFirePossibleEvents(computedMana, game, source);
game.getPlayer(source.getControllerId()).getManaPool().addMana(computedMana, game, source);
checkToFirePossibleEvents(getMana(game, source), game, source);
game.getPlayer(source.getControllerId()).getManaPool().addMana(getMana(game, source), game, source);
return true;
}
@ -111,33 +110,29 @@ public class DynamicManaEffect extends BasicManaEffect {
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
}
public Mana computeMana(boolean netMana, Game game, Ability source) {
public Mana produceMana(boolean netMana, Game game, Ability source) {
Mana computedMana = new Mana();
int count;
if (netMana && netAmount != null) {
// calculate the maximum available mana
// calculate the maximum available manaTemplate
count = netAmount.calculate(game, source, this);
} else {
count = amount.calculate(game, source, this);
}
if (mana.getBlack() > 0) {
if (manaTemplate.getBlack() > 0) {
computedMana.setBlack(count);
} else if (mana.getBlue() > 0) {
} else if (manaTemplate.getBlue() > 0) {
computedMana.setBlue(count);
} else if (mana.getGreen() > 0) {
} else if (manaTemplate.getGreen() > 0) {
computedMana.setGreen(count);
} else if (mana.getRed() > 0) {
} else if (manaTemplate.getRed() > 0) {
computedMana.setRed(count);
} else if (mana.getWhite() > 0) {
} else if (manaTemplate.getWhite() > 0) {
computedMana.setWhite(count);
} else if (mana.getColorless() > 0) {
} else if (manaTemplate.getColorless() > 0) {
computedMana.setColorless(count);
} else if (mana.getAny() > 0) {
} else if (manaTemplate.getAny() > 0) {
if (netMana) {
computedMana.setAny(count);
} else {

View file

@ -72,7 +72,7 @@ public class BattalionAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return new StringBuilder("<i>Battalion</i> - Whenever {this} and at least two other creatures attack, ").append(super.getRule()).toString() ;
return new StringBuilder("<i>Battalion</i> &mdash; Whenever {this} and at least two other creatures attack, ").append(super.getRule()).toString() ;
}
}

View file

@ -65,7 +65,7 @@ public class BloodrushAbility extends ActivatedAbilityImpl {
@Override
public String getRule() {
StringBuilder sb = new StringBuilder("<i>Bloodrush</i> - ");
StringBuilder sb = new StringBuilder("<i>Bloodrush</i> &mdash; ");
sb.append(super.getRule());
return sb.toString();
}

View file

@ -60,7 +60,7 @@ public class ChannelAbility extends ActivatedAbilityImpl {
@Override
public String getRule() {
StringBuilder sb = new StringBuilder("<i>Channel</i> - ");
StringBuilder sb = new StringBuilder("<i>Channel</i> &mdash; ");
sb.append(super.getRule());
if(this.timing == TimingRule.SORCERY) {
sb.append(" Activate this ability only any time you could cast a sorcery.");

View file

@ -103,6 +103,6 @@ public class HeroicAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return new StringBuilder("<i>Heroic</i> - Whenever you cast a spell that targets {this}, ").append(super.getRule()).toString();
return new StringBuilder("<i>Heroic</i> &mdash; Whenever you cast a spell that targets {this}, ").append(super.getRule()).toString();
}
}

View file

@ -71,6 +71,6 @@ public class InspiredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return "<i>Inspired</i> - Whenever {this} becomes untapped, " + super.getRule();
return "<i>Inspired</i> &mdash; Whenever {this} becomes untapped, " + super.getRule();
}
}

View file

@ -27,6 +27,8 @@
*/
package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.ObjectColor;
@ -53,6 +55,7 @@ public class ProtectionAbility extends StaticAbility {
protected Filter filter;
protected boolean removeAuras;
protected static List<ObjectColor> colors = new ArrayList<>();
protected UUID auraIdNotToBeRemoved; // defines an Aura objectId that will not be removed from this protection ability
public ProtectionAbility(Filter filter) {
@ -72,12 +75,15 @@ public class ProtectionAbility extends StaticAbility {
public static ProtectionAbility from(ObjectColor color) {
FilterObject filter = new FilterObject(color.getDescription());
filter.add(new ColorPredicate(color));
colors.add(color);
return new ProtectionAbility(filter);
}
public static ProtectionAbility from(ObjectColor color1, ObjectColor color2) {
FilterObject filter = new FilterObject(color1.getDescription() + " and from " + color2.getDescription());
filter.add(Predicates.or(new ColorPredicate(color1), new ColorPredicate(color2)));
colors.add(color1);
colors.add(color2);
return new ProtectionAbility(filter);
}
@ -140,6 +146,8 @@ public class ProtectionAbility extends StaticAbility {
return removeAuras;
}
public List<ObjectColor> getColors() { return colors; }
public UUID getAuraIdNotToBeRemoved() {
return auraIdNotToBeRemoved;
}

View file

@ -35,7 +35,6 @@ import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TimingRule;
@ -63,9 +62,8 @@ import mage.game.events.ZoneChangeEvent;
public class UnearthAbility extends ActivatedAbilityImpl {
public UnearthAbility(ManaCosts costs) {
super(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), costs);
super(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false, true, true), costs);
this.timing = TimingRule.SORCERY;
this.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.Custom));
this.addEffect(new CreateDelayedTriggeredAbilityEffect(new UnearthDelayedTriggeredAbility()));
this.addEffect(new UnearthLeavesBattlefieldEffect());
}

View file

@ -29,8 +29,8 @@ package mage.abilities.mana;
import mage.abilities.condition.Condition;
import mage.abilities.costs.Cost;
import mage.abilities.effects.common.AddConditionalColorlessManaEffect;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.AddConditionalColorlessManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.Zone;
import mage.game.Game;
@ -38,7 +38,7 @@ public class ActivateIfConditionManaAbility extends ActivatedManaAbilityImpl {
public ActivateIfConditionManaAbility(Zone zone, BasicManaEffect effect, Cost cost, Condition condition) {
super(zone, effect, cost);
this.netMana.add(effect.getMana());
this.netMana.add(effect.getManaTemplate());
this.condition = condition;
}

View file

@ -29,8 +29,8 @@ package mage.abilities.mana;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.effects.common.AddManaOfAnyColorEffect;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.Zone;
import mage.game.Game;
@ -42,7 +42,7 @@ public class ActivateOncePerTurnManaAbility extends ActivatedManaAbilityImpl {
public ActivateOncePerTurnManaAbility(Zone zone, BasicManaEffect effect, Cost cost) {
super(zone, effect, cost);
this.netMana.add(effect.getMana());
this.netMana.add(effect.getManaTemplate());
this.maxActivationsPerTurn = 1;
}

View file

@ -33,6 +33,7 @@ import java.util.UUID;
import mage.Mana;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.Cost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ManaEffect;
import mage.constants.AbilityType;
import mage.constants.AsThoughEffectType;
@ -95,6 +96,13 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
*/
@Override
public List<Mana> getNetMana(Game game) {
if (netMana.isEmpty()) {
for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) {
netMana.addAll(((ManaEffect) effect).getNetMana(game, this));
}
}
}
return netMana;
}

View file

@ -105,6 +105,18 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
controller.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Mana mana = new Mana();
Mana types = getManaTypes(game, source);
Choice choice = new ChoiceColor(true);
choice.getChoices().clear();
@ -143,12 +155,11 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
if (choice.getChoices().size() == 1) {
choice.setChoice(choice.getChoices().iterator().next());
} else {
if (!player.choose(outcome, choice, game)) {
return false;
if (player == null || !player.choose(outcome, choice, game)) {
return null;
}
}
if (choice.getChoice() != null) {
Mana mana = new Mana();
switch (choice.getChoice()) {
case "Black":
mana.setBlack(1);
@ -169,16 +180,9 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
mana.setColorless(1);
break;
}
checkToFirePossibleEvents(mana, game, source);
player.getManaPool().addMana(mana, game, source);
}
}
return true;
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
return mana;
}
private Mana getManaTypes(Game game, Ability source) {
@ -205,6 +209,7 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
return types;
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
List<Mana> netManas = new ArrayList<>();
Mana types = getManaTypes(game, source);

View file

@ -30,7 +30,7 @@ package mage.abilities.mana;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.AddManaOfAnyColorEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.constants.Zone;
public class AnyColorManaAbility extends ActivatedManaAbilityImpl {

View file

@ -82,6 +82,18 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
controller.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Mana mana = new Mana();
Mana types = getManaTypes(game, source);
Choice choice = new ChoiceColor(true);
choice.getChoices().clear();
@ -121,11 +133,11 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
choice.setChoice(choice.getChoices().iterator().next());
} else {
if (!player.choose(outcome, choice, game)) {
return false;
return mana;
}
}
if (choice.getChoice() != null) {
Mana mana = new Mana();
switch (choice.getChoice()) {
case "Black":
mana.setBlack(1);
@ -146,16 +158,9 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
mana.setColorless(1);
break;
}
checkToFirePossibleEvents(mana, game, source);
player.getManaPool().addMana(mana, game, source);
}
}
return true;
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
return mana;
}
private Mana getManaTypes(Game game, Ability source) {
@ -167,19 +172,19 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
return types;
}
inManaTypeCalculation = true;
ObjectColor permanentColor;
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
for (Permanent permanent : permanents) {
permanentColor = permanent.getColor(game);
if(permanentColor.isColorless())
if (permanentColor.isColorless()) {
types.add(Mana.ColorlessMana(1));
else{
} else {
List<ObjectColor> permanentColors = permanent.getColor(game).getColors();
for (ObjectColor color : permanentColors){
types.add(new Mana(color.getColoredManaSymbol()));
for (ObjectColor color : permanentColors) {
types.add(new Mana(color.getOneColoredManaSymbol()));
}
}
}
@ -187,6 +192,7 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
return types;
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
List<Mana> netManas = new ArrayList<>();
Mana types = getManaTypes(game, source);

View file

@ -29,7 +29,7 @@
package mage.abilities.mana;
import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.ColoredManaSymbol;
/**

View file

@ -29,7 +29,7 @@
package mage.abilities.mana;
import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.ColoredManaSymbol;
/**

View file

@ -28,7 +28,7 @@
package mage.abilities.mana;
import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
/**
*

View file

@ -122,6 +122,18 @@ class CommanderIdentityManaEffect extends ManaEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
checkToFirePossibleEvents(getMana(game, source), game, source);
controller.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
return false;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Mana mana = new Mana();
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Choice choice = new ChoiceImpl();
@ -152,10 +164,10 @@ class CommanderIdentityManaEffect extends ManaEffect {
choice.setChoice(choice.getChoices().iterator().next());
} else {
if (!controller.choose(outcome, choice, game)) {
return false;
return mana;
}
}
Mana mana = new Mana();
switch (choice.getChoice()) {
case "Black":
mana.setBlack(1);
@ -173,16 +185,10 @@ class CommanderIdentityManaEffect extends ManaEffect {
mana.setWhite(1);
break;
}
checkToFirePossibleEvents(mana, game, source);
controller.getManaPool().addMana(mana, game, source);
return true;
}
}
return false;
return mana;
}
@Override
public Mana getMana(Game game, Ability source) {
return null;
}
}

View file

@ -33,7 +33,7 @@ import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.AddConditionalManaOfAnyColorEffect;
import mage.abilities.effects.mana.AddConditionalManaOfAnyColorEffect;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.constants.Zone;
import mage.game.Game;

View file

@ -8,7 +8,7 @@ package mage.abilities.mana;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.AddConditionalManaEffect;
import mage.abilities.effects.mana.AddConditionalManaEffect;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.constants.Zone;

View file

@ -8,7 +8,7 @@ package mage.abilities.mana;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.AddConditionalColorlessManaEffect;
import mage.abilities.effects.mana.AddConditionalColorlessManaEffect;
import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.constants.Zone;

View file

@ -33,7 +33,7 @@ import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.common.DynamicManaEffect;
import mage.abilities.effects.mana.DynamicManaEffect;
import mage.constants.Zone;
import mage.game.Game;
@ -111,7 +111,7 @@ public class DynamicManaAbility extends ActivatedManaAbilityImpl {
if (game != null) {
// TODO: effects from replacement effects like Mana Reflection are not considered yet
// TODO: effects that need a X payment (e.g. Mage-Ring Network) return always 0
newNetMana.add(manaEffect.computeMana(true, game, this));
newNetMana.addAll(manaEffect.getNetMana(game, this));
}
return newNetMana;
}

View file

@ -29,7 +29,7 @@
package mage.abilities.mana;
import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.ColoredManaSymbol;
/**

View file

@ -29,7 +29,7 @@
package mage.abilities.mana;
import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.ColoredManaSymbol;
/**

View file

@ -30,9 +30,8 @@ package mage.abilities.mana;
import java.util.List;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.Zone;
import mage.game.Game;
@ -79,15 +78,8 @@ public class SimpleManaAbility extends ActivatedManaAbilityImpl {
@Override
public List<Mana> getNetMana(Game game) {
if (netMana.isEmpty() && predictable) {
for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) {
Mana effectMana = ((ManaEffect) effect).getMana(game, this);
if (effectMana != null) {
netMana.add(effectMana);
}
}
}
if (predictable) {
return super.getNetMana(game);
}
return netMana;
}

View file

@ -32,7 +32,6 @@ import java.util.List;
import mage.Mana;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DynamicManaEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.constants.AbilityType;
import mage.constants.Zone;
@ -72,20 +71,14 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen
*/
@Override
public List<Mana> getNetMana(Game game) {
if (!getEffects().isEmpty()) {
Effect effect = getEffects().get(0);
if (effect != null && game != null) {
ArrayList<Mana> newNetMana = new ArrayList<>();
if (effect instanceof DynamicManaEffect) {
// TODO: effects from replacement effects like Mana Reflection are not considered yet
// TODO: effects that need a X payment (e.g. Mage-Ring Network) return always 0
newNetMana.add(((DynamicManaEffect) effect).computeMana(true, game, this));
} else if (effect instanceof Effect) {
newNetMana.add(((ManaEffect) effect).getMana(game, this));
if (game != null) {
ArrayList<Mana> newNetMana = new ArrayList<>();
for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) {
newNetMana.addAll(((ManaEffect) effect).getNetMana(game, this));
}
return newNetMana;
}
return newNetMana;
}
return netMana;
}

View file

@ -29,7 +29,7 @@
package mage.abilities.mana;
import mage.Mana;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.constants.ColoredManaSymbol;
/**