Merge branch 'master' into Zzooouhh-ugl

This commit is contained in:
L_J 2018-09-30 14:13:00 +02:00 committed by GitHub
commit 1655963937
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
773 changed files with 19669 additions and 1871 deletions

View file

@ -86,10 +86,10 @@ public interface MageObject extends MageItem, Serializable {
void setZoneChangeCounter(int value, Game game);
default boolean isHistoric(){
default boolean isHistoric() {
return getCardType().contains(CardType.ARTIFACT)
|| getSuperType().contains(SuperType.LEGENDARY)
|| hasSubtype(SubType.SAGA, null );
|| hasSubtype(SubType.SAGA, null);
}
default boolean isCreature() {
@ -116,6 +116,10 @@ public interface MageObject extends MageItem, Serializable {
return getCardType().contains(CardType.SORCERY);
}
default boolean isInstantOrSorcery() {
return this.isInstant() || this.isSorcery();
}
default boolean isPlaneswalker() {
return getCardType().contains(CardType.PLANESWALKER);
}

View file

@ -9,7 +9,7 @@ import java.util.UUID;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -158,8 +158,8 @@ public abstract class MageObjectImpl implements MageObject {
@Override
public int getStartingLoyalty() {
for (Ability ab : getAbilities()) {
if (ab instanceof PlanswalkerEntersWithLoyalityCountersAbility) {
return ((PlanswalkerEntersWithLoyalityCountersAbility) ab).getStartingLoyalty();
if (ab instanceof PlaneswalkerEntersWithLoyaltyCountersAbility) {
return ((PlaneswalkerEntersWithLoyaltyCountersAbility) ab).getStartingLoyalty();
}
}
return 0;

View file

@ -1,4 +1,3 @@
package mage.abilities;
import java.io.Serializable;
@ -14,7 +13,6 @@ import mage.abilities.effects.Effects;
import mage.constants.AbilityType;
import mage.constants.AbilityWord;
import mage.constants.EffectType;
import mage.constants.TargetAdjustment;
import mage.constants.Zone;
import mage.game.Controllable;
import mage.game.Game;
@ -23,6 +21,7 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
import mage.target.targetadjustment.TargetAdjuster;
import mage.watchers.Watcher;
/**
@ -527,7 +526,9 @@ public interface Ability extends Controllable, Serializable {
boolean canFizzle();
void setTargetAdjustment(TargetAdjustment targetAdjustment);
void setTargetAdjuster(TargetAdjuster targetAdjuster);
TargetAdjustment getTargetAdjustment();
TargetAdjuster getTargetAdjuster();
void adjustTargets(Game game);
}

View file

@ -1,4 +1,3 @@
package mage.abilities;
import java.util.ArrayList;
@ -33,6 +32,7 @@ import mage.game.stack.StackAbility;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
import mage.target.targetadjustment.TargetAdjuster;
import mage.util.GameLog;
import mage.util.ThreadLocalStringBuilder;
import mage.watchers.Watcher;
@ -72,7 +72,7 @@ public abstract class AbilityImpl implements Ability {
protected List<Watcher> watchers = new ArrayList<>();
protected List<Ability> subAbilities = null;
protected boolean canFizzle = true;
protected TargetAdjustment targetAdjustment = TargetAdjustment.NONE;
protected TargetAdjuster targetAdjuster = null;
public AbilityImpl(AbilityType abilityType, Zone zone) {
this.id = UUID.randomUUID();
@ -119,7 +119,7 @@ public abstract class AbilityImpl implements Ability {
this.sourceObject = ability.sourceObject;
this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter;
this.canFizzle = ability.canFizzle;
this.targetAdjustment = ability.targetAdjustment;
this.targetAdjuster = ability.targetAdjuster;
}
@Override
@ -1225,12 +1225,19 @@ public abstract class AbilityImpl implements Ability {
}
@Override
public void setTargetAdjustment(TargetAdjustment targetAdjustment) {
this.targetAdjustment = targetAdjustment;
public void setTargetAdjuster(TargetAdjuster targetAdjuster) {
this.targetAdjuster = targetAdjuster;
}
@Override
public TargetAdjustment getTargetAdjustment() {
return targetAdjustment;
public TargetAdjuster getTargetAdjuster() {
return targetAdjuster;
}
@Override
public void adjustTargets(Game game) {
if (targetAdjuster != null) {
targetAdjuster.adjustTargets(this, game);
}
}
}

View file

@ -13,7 +13,7 @@ import mage.game.Game;
public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl {
private Duration duration;
private boolean triggerOnlyOnce;
protected boolean triggerOnlyOnce;
public DelayedTriggeredAbility(Effect effect) {
this(effect, Duration.EndOfGame);

View file

@ -1,9 +1,10 @@
package mage.abilities;
import java.io.Serializable;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.target.Target;
import mage.target.Targets;
/**
@ -13,16 +14,23 @@ import mage.target.Targets;
public class Mode implements Serializable {
protected UUID id;
protected Targets targets;
protected Effects effects;
protected final Targets targets;
protected final Effects effects;
public Mode() {
this((Effect) null);
}
public Mode(Effect effect) {
this.id = UUID.randomUUID();
this.targets = new Targets();
this.effects = new Effects();
if (effect != null) {
this.effects.add(effect);
}
}
public Mode(Mode mode) {
public Mode(final Mode mode) {
this.id = mode.id;
this.targets = mode.targets.copy();
this.effects = mode.effects.copy();
@ -44,7 +52,15 @@ public class Mode implements Serializable {
return targets;
}
public void addTarget(Target target) {
targets.add(target);
}
public Effects getEffects() {
return effects;
}
public void addEffect(Effect effect) {
effects.add(effect);
}
}

View file

@ -10,7 +10,6 @@ import mage.constants.Zone;
import mage.game.Game;
/**
*
* @author LevelX2
*/
public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
@ -37,15 +36,12 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
} else {
sb.append(" Activate this ability only ");
}
if (condition.toString() != null) {
if (!condition.toString().startsWith("during")
&& !condition.toString().startsWith("before")) {
sb.append("if ");
}
sb.append(condition.toString()).append('.');
} else {
sb.append(" [Condition toString() == null] ");
if (!condition.toString().startsWith("during")
&& !condition.toString().startsWith("before")) {
sb.append("if ");
}
sb.append(condition.toString()).append('.');
return sb.toString();
}

View file

@ -1,4 +1,3 @@
package mage.abilities.common;
import java.util.Locale;
@ -68,6 +67,7 @@ public class BeginningOfEndStepTriggeredAbility extends TriggeredAbilityImpl {
}
break;
case ANY:
case EACH_PLAYER:
case NEXT:
if (getTargets().isEmpty()) {
for (Effect effect : this.getEffects()) {
@ -123,6 +123,8 @@ public class BeginningOfEndStepTriggeredAbility extends TriggeredAbilityImpl {
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of each opponent's end step, ").toString();
case ANY:
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of each end step, ").toString();
case EACH_PLAYER:
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of each player's end step, ").toString();
case CONTROLLER_ATTACHED_TO:
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of the end step of enchanted permanent's controller, ").toString();
}

View file

@ -31,7 +31,7 @@ public class DealsDamageToOneOrMoreCreaturesTriggeredAbility extends DealsDamage
|| game.getTurn().getStepType() == PhaseStep.FIRST_COMBAT_DAMAGE) {
String stepHash = (String) game.getState().getValue("damageStep" + getOriginalId());
String newStepHash = game.getStep().getType().toString() + game.getTurnNum();
if (stepHash == null || !newStepHash.equals(stepHash)) {
if (!newStepHash.equals(stepHash)) {
// this ability did not trigger during this damage step
game.getState().setValue("damageStep" + getOriginalId(), game.getStep().getType().toString() + game.getTurnNum());
return true;

View file

@ -62,41 +62,40 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl {
if (((ZoneChangeEvent) event).isDiesEvent()) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
boolean triggered = false;
if (zEvent != null) {
if (zEvent.getTarget() != null && zEvent.getTarget().getAttachments() != null && zEvent.getTarget().getAttachments().contains(this.getSourceId())) {
triggered = true;
} else {
// If both (attachment and attached went to graveyard at the same time, the attachemnets can be already removed from the attached object.)
// So check here with the LKI of the enchantment
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
if (attachment != null
&& zEvent.getTargetId() != null && attachment.getAttachedTo() != null
&& zEvent.getTargetId().equals(attachment.getAttachedTo())) {
Permanent attachedTo = game.getPermanentOrLKIBattlefield(attachment.getAttachedTo());
if (attachedTo != null
&& attachment.getAttachedToZoneChangeCounter() == attachedTo.getZoneChangeCounter(game)) { // zoneChangeCounter is stored in Permanent
triggered = true;
if (zEvent.getTarget() != null && zEvent.getTarget().getAttachments() != null && zEvent.getTarget().getAttachments().contains(this.getSourceId())) {
triggered = true;
} else {
// If both (attachment and attached went to graveyard at the same time, the attachemnets can be already removed from the attached object.)
// So check here with the LKI of the enchantment
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
if (attachment != null
&& zEvent.getTargetId() != null && attachment.getAttachedTo() != null
&& zEvent.getTargetId().equals(attachment.getAttachedTo())) {
Permanent attachedTo = game.getPermanentOrLKIBattlefield(attachment.getAttachedTo());
if (attachedTo != null
&& attachment.getAttachedToZoneChangeCounter() == attachedTo.getZoneChangeCounter(game)) { // zoneChangeCounter is stored in Permanent
triggered = true;
}
}
}
if (triggered) {
for (Effect effect : getEffects()) {
if (zEvent.getTarget() != null) {
effect.setValue("attachedTo", zEvent.getTarget());
if (setTargetPointer == SetTargetPointer.ATTACHED_TO_CONTROLLER) {
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
if (attachment != null && attachment.getAttachedTo() != null) {
Permanent attachedTo = (Permanent) game.getLastKnownInformation(attachment.getAttachedTo(), Zone.BATTLEFIELD, attachment.getAttachedToZoneChangeCounter());
if (attachedTo != null) {
effect.setTargetPointer(new FixedTarget(attachedTo.getControllerId()));
}
}
}
}
}
if (triggered) {
for (Effect effect : getEffects()) {
if (zEvent.getTarget() != null) {
effect.setValue("attachedTo", zEvent.getTarget());
if (setTargetPointer == SetTargetPointer.ATTACHED_TO_CONTROLLER) {
Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId());
if (attachment != null && attachment.getAttachedTo() != null) {
Permanent attachedTo = (Permanent) game.getLastKnownInformation(attachment.getAttachedTo(), Zone.BATTLEFIELD, attachment.getAttachedToZoneChangeCounter());
if (attachedTo != null) {
effect.setTargetPointer(new FixedTarget(attachedTo.getControllerId()));
}
}
}
}
}
return true;
}
return true;
}
}
return false;
}

View file

@ -12,17 +12,17 @@ import mage.counters.CounterType;
*
* @author LevelX2
*/
public class PlanswalkerEntersWithLoyalityCountersAbility extends EntersBattlefieldAbility {
public class PlaneswalkerEntersWithLoyaltyCountersAbility extends EntersBattlefieldAbility {
private final int startingLoyalty;
public PlanswalkerEntersWithLoyalityCountersAbility(int loyalty) {
public PlaneswalkerEntersWithLoyaltyCountersAbility(int loyalty) {
super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyalty)));
startingLoyalty = loyalty;
setRuleVisible(false);
}
public PlanswalkerEntersWithLoyalityCountersAbility(final PlanswalkerEntersWithLoyalityCountersAbility ability) {
public PlaneswalkerEntersWithLoyaltyCountersAbility(final PlaneswalkerEntersWithLoyaltyCountersAbility ability) {
super(ability);
startingLoyalty = ability.startingLoyalty;
}
@ -32,7 +32,7 @@ public class PlanswalkerEntersWithLoyalityCountersAbility extends EntersBattlefi
}
@Override
public PlanswalkerEntersWithLoyalityCountersAbility copy() {
return new PlanswalkerEntersWithLoyalityCountersAbility(this);
public PlaneswalkerEntersWithLoyaltyCountersAbility copy() {
return new PlaneswalkerEntersWithLoyaltyCountersAbility(this);
}
}

View file

@ -1,62 +1,62 @@
/*
* 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.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
/**
*
* @author fireshoes
*/
public class SpellCounteredControllerTriggeredAbility extends TriggeredAbilityImpl {
public SpellCounteredControllerTriggeredAbility(Effect effect) {
this(effect, false);
}
public SpellCounteredControllerTriggeredAbility(Effect effect, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
}
public SpellCounteredControllerTriggeredAbility(final SpellCounteredControllerTriggeredAbility ability) {
super(ability);
}
@Override
public SpellCounteredControllerTriggeredAbility copy() {
return new SpellCounteredControllerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.COUNTERED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
StackObject stackObjectThatCountered = game.getStack().getStackObject(event.getSourceId());
if (stackObjectThatCountered == null) {
stackObjectThatCountered = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK);
}
if (stackObjectThatCountered != null && stackObjectThatCountered.isControlledBy(getControllerId())) {
StackObject counteredStackObject = (StackObject) game.getLastKnownInformation(event.getTargetId(), Zone.STACK);
return counteredStackObject != null && (counteredStackObject instanceof Spell);
}
return false;
}
@Override
public String getRule() {
return "Whenever a spell or ability you control counters a spell, " + super.getRule();
}
}
/*
* 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.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
/**
*
* @author fireshoes
*/
public class SpellCounteredControllerTriggeredAbility extends TriggeredAbilityImpl {
public SpellCounteredControllerTriggeredAbility(Effect effect) {
this(effect, false);
}
public SpellCounteredControllerTriggeredAbility(Effect effect, boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
}
public SpellCounteredControllerTriggeredAbility(final SpellCounteredControllerTriggeredAbility ability) {
super(ability);
}
@Override
public SpellCounteredControllerTriggeredAbility copy() {
return new SpellCounteredControllerTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.COUNTERED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
StackObject stackObjectThatCountered = game.getStack().getStackObject(event.getSourceId());
if (stackObjectThatCountered == null) {
stackObjectThatCountered = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK);
}
if (stackObjectThatCountered != null && stackObjectThatCountered.isControlledBy(getControllerId())) {
StackObject counteredStackObject = (StackObject) game.getLastKnownInformation(event.getTargetId(), Zone.STACK);
return (counteredStackObject instanceof Spell);
}
return false;
}
@Override
public String getRule() {
return "Whenever a spell or ability you control counters a spell, " + super.getRule();
}
}

View file

@ -1,40 +1,40 @@
package mage.abilities.condition.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.other.OwnerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author emerald000
*/
public class MeldCondition implements Condition {
private final String meldWithName;
public MeldCondition(String meldWithName) {
this.meldWithName = meldWithName;
}
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceMageObject = source.getSourceObjectIfItStillExists(game);
if (sourceMageObject != null && sourceMageObject instanceof Permanent) {
Permanent sourcePermanent = (Permanent) sourceMageObject;
if (sourcePermanent.isControlledBy(source.getControllerId())
&& sourcePermanent.isOwnedBy(source.getControllerId())) {
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
filter.add(new NamePredicate(this.meldWithName));
filter.add(new OwnerIdPredicate(source.getControllerId()));
return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0;
}
}
return false;
}
}
package mage.abilities.condition.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.other.OwnerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author emerald000
*/
public class MeldCondition implements Condition {
private final String meldWithName;
public MeldCondition(String meldWithName) {
this.meldWithName = meldWithName;
}
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceMageObject = source.getSourceObjectIfItStillExists(game);
if (sourceMageObject instanceof Permanent) {
Permanent sourcePermanent = (Permanent) sourceMageObject;
if (sourcePermanent.isControlledBy(source.getControllerId())
&& sourcePermanent.isOwnedBy(source.getControllerId())) {
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
filter.add(new NamePredicate(this.meldWithName));
filter.add(new OwnerIdPredicate(source.getControllerId()));
return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0;
}
}
return false;
}
}

View file

@ -19,9 +19,9 @@ import mage.game.Game;
*/
public class MostCommonColorCondition implements Condition {
protected ObjectColor compareColor;
protected boolean isMono;
protected Predicate predicate;
protected final ObjectColor compareColor;
protected final boolean isMono;
protected final Predicate predicate;
public MostCommonColorCondition(ObjectColor color) {
this(color, false, null);
@ -31,6 +31,7 @@ public class MostCommonColorCondition implements Condition {
public MostCommonColorCondition(ObjectColor color, boolean isMono, Predicate predicate) {
this.compareColor = color;
this.isMono = isMono;
this.predicate = predicate;
}
@Override

View file

@ -25,6 +25,11 @@ public class HighestConvertedManaCostValue implements DynamicValue {
this.filter = filter;
}
public HighestConvertedManaCostValue(final HighestConvertedManaCostValue dynamicValue){
super();
this.filter = dynamicValue.filter.copy();
}
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
Player controller = game.getPlayer(sourceAbility.getControllerId());
@ -41,7 +46,7 @@ public class HighestConvertedManaCostValue implements DynamicValue {
@Override
public DynamicValue copy() {
return new HighestConvertedManaCostValue();
return new HighestConvertedManaCostValue(this);
}
@Override

View file

@ -0,0 +1,43 @@
package mage.abilities.dynamicvalue.common;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.cards.Card;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
/**
* @author TheElk801
*/
public enum InstantSorceryExileGraveyardCount implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
Player player = game.getPlayer(sourceAbility.getControllerId());
if (player != null) {
int exileCount = 0;
for (Card exiledCard : game.getExile().getAllCards(game)) {
if (exiledCard.getOwnerId().equals(player.getId()) && exiledCard.isInstantOrSorcery()) {
exileCount++;
}
}
return player.getGraveyard().count(
StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, game
) + exileCount;
}
return 0;
}
@Override
public InstantSorceryExileGraveyardCount copy() {
return instance;
}
@Override
public String getMessage() {
return "";
}
}

View file

@ -24,7 +24,7 @@ public class SunburstCount implements DynamicValue {
int count = 0;
if (!game.getStack().isEmpty()) {
StackObject spell = game.getStack().getFirst();
if (spell != null && spell instanceof Spell && ((Spell) spell).getSourceId().equals(source.getSourceId())) {
if (spell instanceof Spell && ((Spell) spell).getSourceId().equals(source.getSourceId())) {
Mana mana = ((Spell) spell).getSpellAbility().getManaCostsToPay().getPayment();
if (mana.getBlack() > 0) {
count++;

View file

@ -12,7 +12,7 @@ import mage.game.Game;
*/
public interface AsThoughEffect extends ContinuousEffect {
boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game);
boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game, UUID playerId);
boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game);

View file

@ -1,4 +1,3 @@
package mage.abilities.effects;
import java.util.UUID;
@ -29,8 +28,12 @@ public abstract class AsThoughEffectImpl extends ContinuousEffectImpl implements
}
@Override
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game) {
return applies(objectId, source, affectedAbility.getControllerId(), game);
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
if (getAsThoughEffectType().equals(AsThoughEffectType.LOOK_AT_FACE_DOWN)) {
return applies(objectId, source, playerId, game);
} else {
return applies(objectId, source, affectedAbility.getControllerId(), game);
}
}
@Override

View file

@ -1,4 +1,3 @@
package mage.abilities.effects;
import java.io.Serializable;
@ -496,7 +495,7 @@ public class ContinuousEffects implements Serializable {
if (effect.applies(objectId, ability, controllerId, game)) {
return new MageObjectReference(ability.getSourceObject(game), game);
}
} else if (effect.applies(objectId, affectedAbility, ability, game)) {
} else if (effect.applies(objectId, affectedAbility, ability, game, controllerId)) {
return new MageObjectReference(ability.getSourceObject(game), game);
}
}
@ -512,7 +511,7 @@ public class ContinuousEffects implements Serializable {
Set<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_ONLY_MANA).getAbility(effect.getId());
for (Ability ability : abilities) {
if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game))
|| effect.applies(objectId, affectedAbility, ability, game)) {
|| effect.applies(objectId, affectedAbility, ability, game, controllerId)) {
if (((AsThoughManaEffect) effect).getAsThoughManaType(manaType, mana, controllerId, ability, game) == null) {
return null;
}
@ -525,7 +524,7 @@ public class ContinuousEffects implements Serializable {
Set<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_OTHER_MANA).getAbility(effect.getId());
for (Ability ability : abilities) {
if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game))
|| effect.applies(objectId, affectedAbility, ability, game)) {
|| effect.applies(objectId, affectedAbility, ability, game, controllerId)) {
ManaType usableManaType = ((AsThoughManaEffect) effect).getAsThoughManaType(manaType, mana, controllerId, ability, game);
if (usableManaType != null) {
return usableManaType;

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.MageObject;
@ -16,18 +15,25 @@ import mage.game.stack.Spell;
public class CastSourceTriggeredAbility extends TriggeredAbilityImpl {
public static final String SOURCE_CAST_SPELL_ABILITY = "sourceCastSpellAbility";
private final String rulePrefix;
public CastSourceTriggeredAbility(Effect effect) {
this(effect, false);
}
public CastSourceTriggeredAbility(Effect effect, boolean optional) {
this(effect, optional, "");
}
public CastSourceTriggeredAbility(Effect effect, boolean optional, String rulePrefix) {
super(Zone.STACK, effect, optional);
this.ruleAtTheTop = true;
this.rulePrefix = rulePrefix;
}
public CastSourceTriggeredAbility(final CastSourceTriggeredAbility ability) {
super(ability);
this.rulePrefix = ability.rulePrefix;
}
@Override
@ -44,7 +50,7 @@ public class CastSourceTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getSourceId().equals(this.getSourceId())) {
MageObject spellObject = game.getObject(sourceId);
if (spellObject != null && (spellObject instanceof Spell)) {
if ((spellObject instanceof Spell)) {
Spell spell = (Spell) spellObject;
if (spell.getSpellAbility() != null) {
for (Effect effect : getEffects()) {
@ -59,6 +65,6 @@ public class CastSourceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return "When you cast {source}, " + super.getRule();
return rulePrefix + "When you cast this spell, " + super.getRule();
}
}

View file

@ -18,7 +18,7 @@ import mage.util.CardUtil;
*/
public class ChooseACardNameEffect extends OneShotEffect {
public static String INFO_KEY = "NAMED_CARD";
public static final String INFO_KEY = "NAMED_CARD";
public enum TypeOfName {

View file

@ -22,7 +22,7 @@ import mage.util.CardUtil;
*/
public class ChooseBasicLandTypeEffect extends OneShotEffect {
public static String VALUE_KEY = "BasicLandType";
public static final String VALUE_KEY = "BasicLandType";
public ChooseBasicLandTypeEffect(Outcome outcome) {
super(outcome);

View file

@ -62,7 +62,7 @@ public class ChooseCreatureTypeEffect extends OneShotEffect {
* @param game
* @return
*/
public static SubType getChoosenCreatureType(UUID objectId, Game game) {
public static SubType getChosenCreatureType(UUID objectId, Game game) {
SubType creatureType = null;
Object savedCreatureType = game.getState().getValue(objectId + "_type");
if (savedCreatureType != null) {

View file

@ -21,7 +21,7 @@ import mage.util.CardUtil;
*/
public class ChooseOpponentEffect extends OneShotEffect {
public static String VALUE_KEY = "_opponent";
public static final String VALUE_KEY = "_opponent";
public ChooseOpponentEffect(Outcome outcome) {
super(outcome);

View file

@ -54,7 +54,7 @@ public class CopyTargetSpellEffect extends OneShotEffect {
if (spell != null) {
StackObject newStackObject = spell.createCopyOnStack(game, source, useController ? spell.getControllerId() : source.getControllerId(), true);
Player player = game.getPlayer(source.getControllerId());
if (player != null && newStackObject != null && newStackObject instanceof Spell) {
if (player != null && newStackObject instanceof Spell) {
String activateMessage = ((Spell) newStackObject).getActivatedMessage(game);
if (activateMessage.startsWith(" casts ")) {
activateMessage = activateMessage.substring(6);

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import java.util.UUID;
@ -71,6 +70,9 @@ public class DamageMultiEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
if (amount.toString().equals("3")) {
return this.sourceName + " deals 3 damage divided as you choose among one, two, or three targets";
}
return this.sourceName + " deals " + amount.toString() + " damage divided as you choose among any number of " + mode.getTargets().get(0).getTargetName();
}

View file

@ -27,7 +27,10 @@ public class DoIfCostPaid extends OneShotEffect {
}
public DoIfCostPaid(Effect effect, Effect effect2, Cost cost) {
this(effect, cost, null, true);
this(effect,effect2,cost,true);
}
public DoIfCostPaid(Effect effect, Effect effect2, Cost cost,boolean optional) {
this(effect, cost, null, optional);
this.otherwiseEffects.add(effect2);
}
@ -54,8 +57,9 @@ public class DoIfCostPaid extends OneShotEffect {
this.optional = effect.optional;
}
public void addEffect(Effect effect) {
public DoIfCostPaid addEffect(Effect effect) {
executingEffects.add(effect);
return this;
}
@Override

View file

@ -39,7 +39,7 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
if (permanent == null && source.getAbilityType() == AbilityType.STATIC) {
if (source.getAbilityType() == AbilityType.STATIC) {
permanent = game.getPermanentEntering(source.getSourceId());
}
}

View file

@ -81,7 +81,7 @@ public class LookLibraryAndPickControllerEffect extends LookLibraryControllerEff
FilterCard pickFilter, Zone targetZoneLookedCards,
boolean putOnTop, boolean reveal) {
this(numberOfCards, mayShuffleAfter, numberToPick, pickFilter,
targetZoneLookedCards, putOnTop, reveal, false);
targetZoneLookedCards, putOnTop, reveal, reveal);
}
public LookLibraryAndPickControllerEffect(int numberOfCards,

View file

@ -6,6 +6,7 @@ import mage.constants.Duration;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectImpl;
import mage.filter.FilterInPlay;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
@ -18,9 +19,9 @@ import mage.players.Player;
*/
public class PreventAllNonCombatDamageToAllEffect extends PreventionEffectImpl {
protected FilterInPlay filter;
protected final FilterPermanent filter;
public PreventAllNonCombatDamageToAllEffect(Duration duration, FilterInPlay filter) {
public PreventAllNonCombatDamageToAllEffect(Duration duration, FilterPermanent filter) {
super(duration, Integer.MAX_VALUE, false);
this.filter = filter;
staticText = "Prevent all non combat damage that would be dealt to " + filter.getMessage() + ' ' + duration.toString();
@ -42,15 +43,7 @@ public class PreventAllNonCombatDamageToAllEffect extends PreventionEffectImpl {
&& !((DamageEvent) event).isCombatDamage()) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) {
if (filter.match(permanent, source.getSourceId(), source.getControllerId(), game)) {
return true;
}
}
else {
Player player = game.getPlayer(event.getTargetId());
if (player != null && filter.match(player, source.getSourceId(), source.getControllerId(), game)) {
return true;
}
return filter.match(permanent, source.getSourceId(), source.getControllerId(), game);
}
}
return false;

View file

@ -37,7 +37,7 @@ public class ReturnToBattlefieldUnderOwnerControlAttachedEffect extends OneShotE
return false;
}
Object object = getValue("attachedTo");
if (object != null && object instanceof Permanent) {
if (object instanceof Permanent) {
Card card = game.getCard(((Permanent) object).getId());
if (card != null) {
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null)) {

View file

@ -66,7 +66,7 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
}
else {
Card card = game.getCard(targetId);
if (card != null && card instanceof MeldCard) {
if (card instanceof MeldCard) {
MeldCard meldCard = (MeldCard) card;
Card topCard = meldCard.getTopHalfCard();
Card bottomCard = meldCard.getBottomHalfCard();

View file

@ -43,7 +43,7 @@ public class ReturnToBattlefieldUnderYourControlAttachedEffect extends OneShotEf
public boolean apply(Game game, Ability source) {
Object object = getValue("attachedTo");
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && object != null && object instanceof Permanent) {
if (controller != null && object instanceof Permanent) {
Card card = game.getCard(((Permanent) object).getId());
// Move the card only, if it is still in the next zone after the battlefield
if (card != null && card.getZoneChangeCounter(game) == ((Permanent) object).getZoneChangeCounter(game) + 1) {

View file

@ -64,7 +64,7 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
}
else {
Card card = game.getCard(targetId);
if (card != null && card instanceof MeldCard) {
if (card instanceof MeldCard) {
MeldCard meldCard = (MeldCard) card;
Card topCard = meldCard.getTopHalfCard();
Card bottomCard = meldCard.getBottomHalfCard();

View file

@ -33,7 +33,7 @@ public class ReturnToHandAttachedEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Object object = getValue("attachedTo");
if (object != null && object instanceof Permanent) {
if (object instanceof Permanent) {
Card card = game.getCard(((Permanent)object).getId());
if (card != null) {
if (card.moveToZone(Zone.HAND, source.getSourceId(), game, false)) {

View file

@ -76,7 +76,7 @@ public class RollPlanarDieEffect extends OneShotEffect {
for (int i = 0; i < chaosEffects.size(); i++) {
Effect effect = chaosEffects.get(i);
Target target = null;
if (chaosTargets != null && chaosTargets.size() > i) {
if (chaosTargets.size() > i) {
target = chaosTargets.get(i);
}
boolean done = false;

View file

@ -47,7 +47,7 @@ public class TransformSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceObject = source.getSourceObjectIfItStillExists(game); // Transform only if it's the same object as the effect was put on the stack
if (sourceObject != null && sourceObject instanceof Permanent) {
if (sourceObject instanceof Permanent) {
Permanent sourcePermanent = (Permanent) sourceObject;
if (sourcePermanent.canTransform(source, game)) {
// check not to transform twice the same side

View file

@ -37,7 +37,7 @@ public class UntapAllThatAttackedEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Watcher watcher = game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getSimpleName());
if (watcher != null && watcher instanceof AttackedThisTurnWatcher) {
if (watcher instanceof AttackedThisTurnWatcher) {
Set<MageObjectReference> attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures();
for (MageObjectReference mor : attackedThisTurn) {
Permanent permanent = mor.getPermanent(game);

View file

@ -25,7 +25,7 @@ public class AttacksIfAbleSourceEffect extends RequirementEffect {
super(duration);
this.eachCombat = eachCombat;
if (this.duration == Duration.EndOfTurn) {
staticText = "{this} attacks " + (eachCombat ? "each combat" : "this turn") + " if able";
staticText = "{this} attacks " + (eachCombat ? "each combat" : "this combat") + " if able";
} else {
staticText = "{this} attacks each " + (eachCombat ? "combat" : "turn") + " if able";
}

View file

@ -43,7 +43,7 @@ public class ActivateAbilitiesAnyTimeYouCouldCastInstantEffect extends AsThoughE
}
@Override
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game) {
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
return affectedAbility.isControlledBy(source.getControllerId())
&& activatedAbility.isInstance(affectedAbility);
}

View file

@ -15,8 +15,8 @@ import mage.game.permanent.Permanent;
public class AddCardSubtypeAllEffect extends ContinuousEffectImpl {
private static FilterPermanent filter;
private static SubType addedSubtype;
private FilterPermanent filter;
private SubType addedSubtype;
public AddCardSubtypeAllEffect(FilterPermanent _filter, SubType _addedSubtype, DependencyType _dependency) {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
@ -28,6 +28,8 @@ public class AddCardSubtypeAllEffect extends ContinuousEffectImpl {
public AddCardSubtypeAllEffect(final AddCardSubtypeAllEffect effect) {
super(effect);
filter = effect.filter.copy();
addedSubtype = effect.addedSubtype;
}
@Override

View file

@ -22,7 +22,7 @@ public class AddChosenSubtypeEffect extends ContinuousEffectImpl {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(permanent.getId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game);
if (subType != null && !permanent.hasSubtype(subType, game)) {
permanent.getSubtype(game).add(subType);
}

View file

@ -49,7 +49,7 @@ public class BoostAllOfChosenSubtypeEffect extends BoostAllEffect {
@Override
protected void setRuntimeData(Ability source, Game game) {
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(source.getSourceId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game);
if (subType != null) {
subtype = subType;
} else {

View file

@ -32,7 +32,7 @@ public class SwitchPowerToughnessTargetEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(source.getFirstTarget());
Permanent target = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (target != null) {
int power = target.getPower().getValue();
target.getPower().setValue(target.getToughness().getValue());

View file

@ -37,7 +37,7 @@ public class SpellsCostReductionAllOfChosenSubtypeEffect extends SpellsCostReduc
@Override
protected boolean selectedByRuntimeData(Card card, Ability source, Game game) {
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(source.getSourceId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(source.getSourceId(), game);
if (subType != null) {
return card.hasSubtype(subType, game);
}

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common.search;
import mage.MageObject;
@ -28,10 +27,14 @@ public class SearchLibraryGraveyardPutInHandEffect extends OneShotEffect {
}
public SearchLibraryGraveyardPutInHandEffect(FilterCard filter, boolean forceToSearchBoth) {
this(filter, forceToSearchBoth, false);
}
public SearchLibraryGraveyardPutInHandEffect(FilterCard filter, boolean forceToSearchBoth, boolean youMay) {
super(Outcome.Benefit);
this.filter = filter;
this.forceToSearchBoth = forceToSearchBoth;
staticText = "search your library and" + (forceToSearchBoth ? "" : "/or") + " graveyard for a card named " + filter.getMessage()
staticText = (youMay ? "You may" : "") + "search your library and" + (forceToSearchBoth ? "" : "/or") + " graveyard for a card named " + filter.getMessage()
+ ", reveal it, and put it into your hand. " + (forceToSearchBoth ? "Then shuffle your library" : "If you search your library this way, shuffle it");
}

View file

@ -24,7 +24,7 @@ import mage.util.CardUtil;
public class FatesealEffect extends OneShotEffect {
protected static FilterCard filter1 = new FilterCard("card to put on the bottom of opponent's library");
protected static final FilterCard filter1 = new FilterCard("card to put on the bottom of opponent's library");
protected int fatesealNumber;

View file

@ -1,10 +1,8 @@
package mage.abilities.effects.keyword;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@ -15,8 +13,6 @@ import mage.util.CardUtil;
*/
public class ScryEffect extends OneShotEffect {
protected static FilterCard filter1 = new FilterCard("card to put on the bottom of your library");
protected int scryNumber;
public ScryEffect(int scryNumber) {

View file

@ -0,0 +1,54 @@
package mage.abilities.effects.keyword;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author TheElk801
*/
public class SurveilEffect extends OneShotEffect {
protected int surveilNumber;
public SurveilEffect(int scryNumber) {
super(Outcome.Benefit);
this.surveilNumber = scryNumber;
this.setText();
}
public SurveilEffect(final SurveilEffect effect) {
super(effect);
this.surveilNumber = effect.surveilNumber;
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
return player.surveil(surveilNumber, source, game);
}
return false;
}
@Override
public SurveilEffect copy() {
return new SurveilEffect(this);
}
private void setText() {
StringBuilder sb = new StringBuilder("surveil ").append(surveilNumber);
if (surveilNumber == 1) {
sb.append(". <i>(Look at the top card of your library. You may put that card into your graveyard.)</i>");
} else {
sb.append(". <i>(Look at the top ");
sb.append(CardUtil.numberToText(surveilNumber));
sb.append(" cards of your library, then put any number of them into your graveyard and the rest on top in any order.)</i>");
}
staticText = sb.toString();
}
}

View file

@ -16,12 +16,17 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
protected final int amount;
protected final ArrayList<Mana> netMana = new ArrayList<>();
protected final boolean setFlag;
public AddManaOfAnyColorEffect() {
this(1);
}
public AddManaOfAnyColorEffect(int amount) {
this(amount, false);
}
public AddManaOfAnyColorEffect(int amount, boolean setFlag) {
super(new Mana(0, 0, 0, 0, 0, 0, amount, 0));
this.amount = amount;
netMana.add(Mana.GreenMana(amount));
@ -30,12 +35,14 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
netMana.add(Mana.WhiteMana(amount));
netMana.add(Mana.RedMana(amount));
this.staticText = "add " + CardUtil.numberToText(amount) + " mana of any " + (amount > 1 ? "one " : "") + "color";
this.setFlag = setFlag;
}
public AddManaOfAnyColorEffect(final AddManaOfAnyColorEffect effect) {
super(effect);
this.amount = effect.amount;
this.netMana.addAll(effect.netMana);
this.setFlag = effect.setFlag;
}
@Override
@ -66,7 +73,9 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
ChoiceColor choice = new ChoiceColor(true, mes, game.getObject(source.getSourceId()));
if (controller.choose(outcome, choice, game)) {
if (choice.getColor() != null) {
return choice.getMana(amount);
Mana mana = choice.getMana(amount);
mana.setFlag(setFlag);
return mana;
}
}
}

View file

@ -149,7 +149,7 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
// wants to do that in the future.
UUID sourceId = source.getSourceId();
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null && sourceCard instanceof SplitCardHalf) {
if (sourceCard instanceof SplitCardHalf) {
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
sourceId = sourceCard.getId();
}
@ -170,7 +170,7 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
UUID sourceId = source.getSourceId();
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null && sourceCard instanceof SplitCardHalf) {
if (sourceCard instanceof SplitCardHalf) {
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
sourceId = sourceCard.getId();
}

View file

@ -22,7 +22,7 @@ import mage.players.Player;
*/
public class AscendAbility extends SimpleStaticAbility {
public static String ASCEND_RULE = "Ascend <i>(If you control ten or more permanents, you get the city's blessing for the rest of the game.)</i>";
public static final String ASCEND_RULE = "Ascend <i>(If you control ten or more permanents, you get the city's blessing for the rest of the game.)</i>";
public AscendAbility() {
super(Zone.BATTLEFIELD, new AscendContinuousEffect());

View file

@ -272,7 +272,7 @@ class ConspireEffect extends OneShotEffect {
Card card = game.getCard(conspiredSpell.getSourceId());
if (card != null) {
StackObject newStackObject = conspiredSpell.createCopyOnStack(game, source, source.getControllerId(), true);
if (newStackObject != null && newStackObject instanceof Spell && !game.isSimulation()) {
if (newStackObject instanceof Spell && !game.isSimulation()) {
game.informPlayers(controller.getLogName() + ((Spell) newStackObject).getActivatedMessage(game));
}
return true;

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword;
import java.util.ArrayList;
@ -25,6 +24,7 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.ManaPool;
import mage.players.Player;
@ -223,6 +223,7 @@ class ConvokeEffect extends OneShotEffect {
manaPool.unlockManaType(ManaType.COLORLESS);
manaName = "colorless";
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CONVOKED, perm.getId(), source.getSourceId(), source.getControllerId()));
game.informPlayers("Convoke: " + controller.getLogName() + " taps " + perm.getLogName() + " to pay one " + manaName + " mana");
}

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword;
import java.util.UUID;
@ -158,7 +157,7 @@ public class FlashbackAbility extends SpellAbility {
}
/**
* Used for split card sin PlayerImpl method:
* Used for split card in PlayerImpl method:
* getOtherUseableActivatedAbilities
*
* @param abilityName

View file

@ -83,7 +83,7 @@ public class HauntAbility extends TriggeredAbilityImpl {
if (card != null) {
String key = new StringBuilder("Haunting_").append(getSourceId().toString()).append('_').append(card.getZoneChangeCounter(game)).toString();
Object object = game.getState().getValue(key);
if (object != null && object instanceof FixedTarget) {
if (object instanceof FixedTarget) {
FixedTarget target = (FixedTarget) object;
if (target.getTarget() != null && target.getTarget().equals(event.getTargetId())) {
usedFromExile = true;

View file

@ -0,0 +1,142 @@
package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.targetpointer.FixedTarget;
/**
* Jump-start is found on instants and sorceries. You can cast a card with
* jump-start from your graveyard by paying all its regular costs and one
* additional cost: discarding a card from your hand. Casting a spell with
* jump-start follows all the normal timing rules, so sorceries with jump-start
* are still limited to your main phases. A spell with jump-start that was cast
* from your graveyard can still be countered, and if it has targets, it won't
* do anything if all its targets disappear or otherwise become illegal. After a
* spell with jump-start cast from your graveyard resolves, is countered, or
* leaves the stack in any way, it's exiled.
*
* @author TheElk801
*/
public class JumpStartAbility extends SpellAbility {
private boolean replacementEffectAdded = false;
public JumpStartAbility(Card card) {
super(card.getManaCost(), card.getName() + " with jump-start", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE);
this.getCosts().addAll(card.getSpellAbility().getCosts().copy());
Cost cost = new DiscardTargetCost(new TargetCardInHand());
cost.setText("");
this.addCost(cost);
this.getEffects().addAll(card.getSpellAbility().getEffects().copy());
this.getTargets().addAll(card.getSpellAbility().getTargets().copy());
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
this.timing = card.getSpellAbility().getTiming();
}
public JumpStartAbility(final JumpStartAbility ability) {
super(ability);
this.replacementEffectAdded = ability.replacementEffectAdded;
}
@Override
public SpellAbility getSpellAbilityToResolve(Game game) {
Card card = game.getCard(getSourceId());
if (card != null) {
if (!replacementEffectAdded) {
replacementEffectAdded = true;
ContinuousEffect effect = new JumpStartReplacementEffect();
effect.setTargetPointer(new FixedTarget(getSourceId(), game.getState().getZoneChangeCounter(getSourceId())));
game.addEffect(effect, this);
}
}
return this;
}
@Override
public JumpStartAbility copy() {
return new JumpStartAbility(this);
}
@Override
public String getRule(boolean all) {
return getRule();
}
@Override
public String getRule() {
return "Jump-start <i>(You may cast this card from your graveyard "
+ "by discarding a card in addition to paying its other costs. "
+ "Then exile this card.)</i>";
}
}
class JumpStartReplacementEffect extends ReplacementEffectImpl {
public JumpStartReplacementEffect() {
super(Duration.OneUse, Outcome.Exile);
staticText = "(If this spell was cast with jump-start, "
+ "exile it instead of putting it anywhere else "
+ "any time it would leave the stack)";
}
public JumpStartReplacementEffect(final JumpStartReplacementEffect effect) {
super(effect);
}
@Override
public JumpStartReplacementEffect copy() {
return new JumpStartReplacementEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = game.getCard(event.getTargetId());
if (card != null) {
discard();
return controller.moveCards(
card, Zone.EXILED, source, game, false, false, false, event.getAppliedEffects());
}
}
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getTargetId().equals(source.getSourceId())
&& ((ZoneChangeEvent) event).getFromZone() == Zone.STACK
&& ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) {
if (game.getState().getZoneChangeCounter(source.getSourceId()) == source.getSourceObjectZoneChangeCounter() + 1) {
return true;
}
}
return false;
}
}

View file

@ -71,7 +71,7 @@ public class MadnessAbility extends StaticAbility {
return new MadnessAbility(this);
}
public static Condition GetCondition() {
public static Condition getCondition() {
return MadnessCondition.instance;
}

View file

@ -0,0 +1,56 @@
package mage.abilities.keyword;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.Card;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author TheElk801
*/
public class MentorAbility extends AttacksTriggeredAbility {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature with lesser power");
static {
filter.add(new AttackingPredicate());
filter.add(new MentorAbilityPredicate());
}
public MentorAbility() {
super(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
this.addTarget(new TargetCreaturePermanent(filter));
}
public MentorAbility(final MentorAbility ability) {
super(ability);
}
@Override
public String getRule() {
return "mentor <i>(Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)</i>";
}
@Override
public MentorAbility copy() {
return new MentorAbility(this);
}
}
class MentorAbilityPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<Card>> {
@Override
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(input.getSourceId());
return sourcePermanent != null && input.getObject().getPower().getValue() < sourcePermanent.getPower().getValue();
}
}

View file

@ -283,7 +283,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
mageObject.getManaCost().clear();
if (mageObject instanceof Permanent) {
((Permanent) mageObject).setExpansionSetCode("");
((Permanent) mageObject).setRarity(Rarity.NA);
((Permanent) mageObject).setRarity(Rarity.SPECIAL);
}
}

View file

@ -104,7 +104,7 @@ class OfferingAsThoughEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game) {
public boolean applies(UUID sourceId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
if (sourceId.equals(source.getSourceId())) {
Card card = game.getCard(sourceId);
if (!card.isOwnedBy(source.getControllerId())) {

View file

@ -222,7 +222,7 @@ class ReplicateCopyEffect extends OneShotEffect {
// create the copies
for (int i = 0; i < replicateCount; i++) {
StackObject newStackObject = spell.createCopyOnStack(game, source, source.getControllerId(), true);
if (newStackObject != null && newStackObject instanceof Spell && !game.isSimulation()) {
if (newStackObject instanceof Spell && !game.isSimulation()) {
game.informPlayers(controller.getLogName() + ((Spell) newStackObject).getActivatedMessage(game));
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.mana;
import mage.Mana;
@ -8,13 +7,18 @@ import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.constants.Zone;
public class AnyColorManaAbility extends ActivatedManaAbilityImpl {
public AnyColorManaAbility() {
this(new TapSourceCost());
}
public AnyColorManaAbility(Cost cost) {
super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(), cost);
this.netMana.add(new Mana(0,0,0,0,0,0,1, 0));
this(cost, false);
}
public AnyColorManaAbility(Cost cost, boolean setFlag) {
super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(1, setFlag), cost);
this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0));
}
public AnyColorManaAbility(final AnyColorManaAbility ability) {

View file

@ -1,4 +1,3 @@
package mage.cards;
import mage.MageObject;
@ -6,25 +5,12 @@ import mage.MageObjectImpl;
import mage.Mana;
import mage.ObjectColor;
import mage.abilities.*;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.repository.PluginClassloaderRegistery;
import mage.constants.*;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.counters.Counters;
import mage.filter.FilterCard;
import mage.filter.FilterMana;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.game.*;
import mage.game.command.CommandObject;
import mage.game.events.GameEvent;
@ -32,11 +18,6 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.TargetSpell;
import mage.target.common.TargetCardInOpponentsGraveyard;
import mage.target.common.TargetCreaturePermanent;
import mage.util.GameLog;
import mage.util.SubTypeList;
import mage.watchers.Watcher;
@ -351,110 +332,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
// }
@Override
public void adjustTargets(Ability ability, Game game) {
int xValue;
TargetPermanent oldTargetPermanent;
FilterPermanent permanentFilter;
int minTargets;
int maxTargets;
switch (ability.getTargetAdjustment()) {
case NONE:
break;
case X_CMC_EQUAL_PERM:
xValue = ability.getManaCostsToPay().getX();
oldTargetPermanent = (TargetPermanent) ability.getTargets().get(0);
minTargets = oldTargetPermanent.getMinNumberOfTargets();
maxTargets = oldTargetPermanent.getMaxNumberOfTargets();
permanentFilter = oldTargetPermanent.getFilter().copy();
permanentFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue));
ability.getTargets().clear();
ability.getTargets().add(new TargetPermanent(minTargets, maxTargets, permanentFilter, false));
break;
case X_TARGETS:
xValue = ability.getManaCostsToPay().getX();
permanentFilter = ((TargetPermanent) ability.getTargets().get(0)).getFilter();
ability.getTargets().clear();
ability.addTarget(new TargetPermanent(xValue, permanentFilter));
break;
case X_POWER_LEQ:// Minamo Sightbender only
xValue = ability.getManaCostsToPay().getX();
oldTargetPermanent = (TargetPermanent) ability.getTargets().get(0);
minTargets = oldTargetPermanent.getMinNumberOfTargets();
maxTargets = oldTargetPermanent.getMaxNumberOfTargets();
permanentFilter = oldTargetPermanent.getFilter().copy();
permanentFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1));
ability.getTargets().clear();
ability.getTargets().add(new TargetPermanent(minTargets, maxTargets, permanentFilter, false));
break;
case VERSE_COUNTER_TARGETS:
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId());
if (sourcePermanent != null) {
xValue = sourcePermanent.getCounters(game).getCount(CounterType.VERSE);
permanentFilter = ((TargetPermanent) ability.getTargets().get(0)).getFilter();
ability.getTargets().clear();
ability.addTarget(new TargetPermanent(0, xValue, permanentFilter, false));
}
break;
case X_CMC_EQUAL_GY_CARD: //Geth, Lord of the Vault only
xValue = ability.getManaCostsToPay().getX();
TargetCard oldTarget = (TargetCard) ability.getTargets().get(0);
FilterCard filterCard = oldTarget.getFilter().copy();
filterCard.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue));
ability.getTargets().clear();
ability.getTargets().add(new TargetCardInOpponentsGraveyard(filterCard));
break;
case CHOSEN_NAME: //Declaration of Naught only
ability.getTargets().clear();
FilterSpell filterSpell = new FilterSpell("spell with the chosen name");
filterSpell.add(new NamePredicate((String) game.getState().getValue(ability.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY)));
TargetSpell target = new TargetSpell(1, filterSpell);
ability.addTarget(target);
break;
case CHOSEN_COLOR: //Pentarch Paladin only
ObjectColor chosenColor = (ObjectColor) game.getState().getValue(ability.getSourceId() + "_color");
ability.getTargets().clear();
FilterPermanent filter = new FilterPermanent("permanent of the chosen color.");
if (chosenColor != null) {
filter.add(new ColorPredicate(chosenColor));
} else {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, -5));// Pretty sure this is always false
}
oldTargetPermanent = new TargetPermanent(filter);
ability.addTarget(oldTargetPermanent);
break;
case TREASURE_COUNTER_POWER: //Legacy's Allure only
sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId());
if (sourcePermanent != null) {
xValue = sourcePermanent.getCounters(game).getCount(CounterType.TREASURE);
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature with power less than or equal to the number of treasure counters on {this}");
filter2.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1));
ability.getTargets().clear();
ability.getTargets().add(new TargetCreaturePermanent(filter2));
}
break;
case SIMIC_MANIPULATOR: //Simic Manipulator only
xValue = 0;
for (Cost cost : ability.getCosts()) {
if (cost instanceof RemoveVariableCountersTargetCost) {
xValue = ((RemoveVariableCountersTargetCost) cost).getAmount();
break;
}
}
ability.getTargets().clear();
FilterCreaturePermanent newFilter = new FilterCreaturePermanent("creature with power less than or equal to " + xValue);
newFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, xValue + 1));
ability.addTarget(new TargetCreaturePermanent(newFilter));
break;
case CREATURE_POWER_X_OR_LESS: // Aryel, Knight of Windgrace
int value = 0;
for (VariableCost cost : ability.getCosts().getVariableCosts()) {
value = cost.getAmount();
}
FilterCreaturePermanent filterCreaturePermanent = new FilterCreaturePermanent("creature with power " + value + " or less");
filterCreaturePermanent.add(new PowerPredicate(ComparisonType.FEWER_THAN, value + 1));
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanent(filterCreaturePermanent));
break;
}
ability.adjustTargets(game);
}
@Override

View file

@ -185,7 +185,7 @@ public abstract class ExpansionSet implements Serializable {
return theBooster;
}
protected int AddMissingPartner(List<Card> booster, boolean partnerAllowed, int max, int i) {
protected int addMissingPartner(List<Card> booster, boolean partnerAllowed, int max, int i) {
for (Ability ability : booster.get(booster.size() - 1).getAbilities()) {
//Check if fetched card has the PartnerWithAbility
@ -328,7 +328,7 @@ public abstract class ExpansionSet implements Serializable {
for (int i = 0; i < numBoosterUncommon; i++) {
while (true) {
addToBooster(booster, uncommons);
int check = AddMissingPartner(booster, partnerAllowed, numBoosterUncommon - 1, i);
int check = addMissingPartner(booster, partnerAllowed, numBoosterUncommon - 1, i);
if (check == 1) {
break;
}
@ -358,7 +358,7 @@ public abstract class ExpansionSet implements Serializable {
if (ratioBoosterMythic > 0 && RandomUtil.nextInt(ratioBoosterMythic) == 0) {
while (true) {
addToBooster(booster, mythics);
int check = AddMissingPartner(booster, partnerAllowed, -1, 1);
int check = addMissingPartner(booster, partnerAllowed, -1, 1);
if (check == 1) {
break;
}
@ -370,7 +370,7 @@ public abstract class ExpansionSet implements Serializable {
} else {
while (true) {
addToBooster(booster, rares);
int check = AddMissingPartner(booster, partnerAllowed, -1, 1);
int check = addMissingPartner(booster, partnerAllowed, -1, 1);
if (check == 1) {
break;
}

View file

@ -135,7 +135,7 @@ public class Sets extends HashMap<String, ExpansionSet> {
if (onlyBasicLands) {
// lands is colorless
// discard not needed color by mana produce
Assert.assertEquals("only basic lands allow", 1, card.getMana().size());
Assert.assertEquals("only basic lands allow, but found " + card.getName(), 1, card.getMana().size());
for (Mana manaLand : card.getMana()) {
if (manaLand.getWhite() > 0 && !manaNeed.isWhite()) { cardManaOK = false; }
if (manaLand.getBlue() > 0 && !manaNeed.isBlue()) { cardManaOK = false; }

View file

@ -17,8 +17,8 @@ public class Constructed extends DeckValidator {
private static final Logger logger = Logger.getLogger(DeckValidator.class);
protected static List<String> anyNumberCardsAllowed = new ArrayList<>(Arrays.asList("Relentless Rats", "Shadowborn Apostle", "Rat Colony"));
protected static List<String> basicLandNames = new ArrayList<>(
protected static final List<String> anyNumberCardsAllowed = new ArrayList<>(Arrays.asList("Relentless Rats", "Shadowborn Apostle", "Rat Colony"));
protected static final List<String> basicLandNames = new ArrayList<>(
Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes", "Snow-Covered Forest",
"Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains"));
protected List<String> banned = new ArrayList<>();

View file

@ -12,7 +12,7 @@ import mage.cards.decks.DeckCardLists;
*/
public final class DeckImporterUtil {
public static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "};
private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "};
public static boolean haveSideboardSection(String file) {
// search for sideboard section:

View file

@ -16,9 +16,9 @@ import mage.cards.repository.CardRepository;
*/
public class TxtDeckImporter extends DeckImporter {
public static final String[] SET_VALUES = new String[]{"lands", "creatures", "planeswalkers", "other spells", "sideboard cards",
private static final String[] SET_VALUES = new String[]{"lands", "creatures", "planeswalkers", "other spells", "sideboard cards",
"Instant", "Land", "Enchantment", "Artifact", "Sorcery", "Planeswalker", "Creature"};
public static final Set<String> IGNORE_NAMES = new HashSet<>(Arrays.asList(SET_VALUES));
private static final Set<String> IGNORE_NAMES = new HashSet<>(Arrays.asList(SET_VALUES));
private boolean sideboard = false;
private boolean switchSideboardByEmptyLine = true; // all cards after first empty line will be sideboard (like mtgo format)

View file

@ -9,7 +9,7 @@ import java.util.stream.Collectors;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.cards.*;
import mage.cards.mock.MockCard;
import mage.cards.mock.MockSplitCard;
@ -181,8 +181,8 @@ public class CardInfo {
// Starting loyalty
if (card.isPlaneswalker()) {
for (Ability ab : card.getAbilities()) {
if (ab instanceof PlanswalkerEntersWithLoyalityCountersAbility) {
this.startingLoyalty = "" + ((PlanswalkerEntersWithLoyalityCountersAbility) ab).getStartingLoyalty();
if (ab instanceof PlaneswalkerEntersWithLoyaltyCountersAbility) {
this.startingLoyalty = "" + ((PlaneswalkerEntersWithLoyaltyCountersAbility) ab).getStartingLoyalty();
}
}
if (this.startingLoyalty == null) {

View file

@ -32,7 +32,7 @@ public enum CardRepository {
// raise this if db structure was changed
private static final long CARD_DB_VERSION = 51;
// raise this if new cards were added to the server
private static final long CARD_CONTENT_VERSION = 118;
private static final long CARD_CONTENT_VERSION = 120;
private Dao<CardInfo, Object> cardDao;
private Set<String> classNames;

View file

@ -29,7 +29,7 @@ public enum ExpansionRepository {
private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE";
private static final String VERSION_ENTITY_NAME = "expansion";
private static final long EXPANSION_DB_VERSION = 5;
private static final long EXPANSION_CONTENT_VERSION = 16;
private static final long EXPANSION_CONTENT_VERSION = 17;
private Dao<ExpansionInfo, Object> expansionDao;

View file

@ -43,6 +43,7 @@ public enum AbilityWord {
SWEEP("Sweep"),
TEMPTING_OFFER("Tempting offer"),
THRESHOLD("Threshold"),
UNDERGROWTH("Undergrowth"),
WILL_OF_THE_COUNCIL("Will of the council");
private final String text;

View file

@ -6,7 +6,6 @@ package mage.constants;
*/
public enum Rarity {
NA ("na", "na", "N", 0),
LAND ("Land", "common", "C", 1),
COMMON ("Common", "common", "C", 1),
UNCOMMON ("Uncommon", "uncommon", "U", 2),

View file

@ -1,18 +0,0 @@
package mage.constants;
/**
*
* @author TheElk801
*/
public enum TargetAdjustment {
NONE,
X_TARGETS,
X_CMC_EQUAL_PERM,
X_CMC_EQUAL_GY_CARD,
X_POWER_LEQ, CHOSEN_NAME,
CHOSEN_COLOR,
VERSE_COUNTER_TARGETS,
TREASURE_COUNTER_POWER,
SIMIC_MANIPULATOR,
CREATURE_POWER_X_OR_LESS
}

View file

@ -6,5 +6,5 @@ package mage.constants;
*/
public enum TargetController {
ACTIVE, ANY, YOU, NOT_YOU, OPPONENT, TEAM, OWNER, CONTROLLER_ATTACHED_TO, NEXT
ACTIVE, ANY, YOU, NOT_YOU, OPPONENT, TEAM, OWNER, CONTROLLER_ATTACHED_TO, NEXT, EACH_PLAYER
}

View file

@ -1,4 +1,3 @@
package mage.counters;
/**
@ -55,6 +54,7 @@ public enum CounterType {
GROWTH("growth"),
HATCHLING("hatchling"),
HEALING("healing"),
HIT("hit"),
HOOFPRINT("hoofprint"),
HOUR("hour"),
HOURGLASS("hourglass"),

View file

@ -19,7 +19,7 @@ public class ChosenSubtypePredicate implements ObjectPlayerPredicate<ObjectSourc
@Override
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
SubType subType = ChooseCreatureTypeEffect.getChoosenCreatureType(input.getSourceId(), game);
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(input.getSourceId(), game);
return input.getObject().hasSubtype(subType, game);
}

View file

@ -1,16 +1,15 @@
package mage.filter.predicate.permanent;
import mage.cards.Card;
import mage.counters.CounterType;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author jeffwadsworth
*/
public class CounterPredicate implements Predicate<Permanent> {
public class CounterPredicate implements Predicate<Card> {
private final CounterType counter;
@ -23,7 +22,7 @@ public class CounterPredicate implements Predicate<Permanent> {
}
@Override
public boolean apply(Permanent input, Game game) {
public boolean apply(Card input, Game game) {
if (counter == null) {
return !input.getCounters(game).keySet().isEmpty();
} else {

View file

@ -1191,7 +1191,7 @@ public abstract class GameImpl implements Game, Serializable {
player.shuffleLibrary(null, this);
int deduction = 1;
if (freeMulligans > 0) {
if (usedFreeMulligans != null && usedFreeMulligans.containsKey(player.getId())) {
if (usedFreeMulligans.containsKey(player.getId())) {
int used = usedFreeMulligans.get(player.getId());
if (used < freeMulligans) {
deduction = 0;
@ -1424,7 +1424,7 @@ public abstract class GameImpl implements Game, Serializable {
} else {
spellControllerId = spell.getControllerId(); // i.e. resolved spell is the target opponent's spell
}
if (commandedBy != null && spellControllerId != null) {
if (spellControllerId != null) {
Player turnController = getPlayer(commandedBy);
if (turnController != null) {
Player targetPlayer = getPlayer(spellControllerId);
@ -1987,7 +1987,8 @@ public abstract class GameImpl implements Game, Serializable {
if (card != null && card.isCreature()) {
UUID wasAttachedTo = perm.getAttachedTo();
perm.attachTo(null, this);
BestowAbility.becomeCreature(perm, this);
//moved to mage.game.permanent.PermanentImpl::detachAllAttachments
//BestowAbility.becomeCreature(perm, this);
fireEvent(new GameEvent(GameEvent.EventType.UNATTACHED, wasAttachedTo, perm.getId(), perm.getControllerId()));
} else if (movePermanentToGraveyardWithInfo(perm)) {
somethingHappened = true;

View file

@ -10,6 +10,7 @@ import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.command.Commander;
import mage.game.events.ZoneChangeEvent;
import mage.game.events.ZoneChangeGroupEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.permanent.PermanentMeld;
@ -25,6 +26,12 @@ public final class ZonesHandler {
public static boolean cast(ZoneChangeInfo info, Game game) {
if (maybeRemoveFromSourceZone(info, game)) {
placeInDestinationZone(info, game);
// create a group zone change event if a card is moved to stack for casting (it's always only one card, but some effects check for group events (one or more xxx))
Set<Card> cards = new HashSet<>();
Card targetCard = getTargetCard(game, info.event.getTargetId());
cards.add(targetCard);
game.fireEvent(new ZoneChangeGroupEvent(cards, info.event.getSourceId(), info.event.getPlayerId(), info.event.getFromZone(), info.event.getToZone()));
// normal movement
game.fireEvent(info.event);
return true;
}

View file

@ -286,7 +286,7 @@ public class Plane implements CommandObject {
Class<?> c = Class.forName(planeName);
Constructor<?> cons = c.getConstructor();
Object plane = cons.newInstance();
if (plane != null && plane instanceof mage.game.command.Plane) {
if (plane instanceof Plane) {
return (Plane) plane;
}
} catch (Exception ex) {

View file

@ -11,7 +11,7 @@ import mage.game.permanent.token.CatToken2;
*
* @author TheElk801
*/
public class AjaniAdversaryOfTyrantsEmblem extends Emblem {
public final class AjaniAdversaryOfTyrantsEmblem extends Emblem {
// 7: You get an emblem with "At the beginning of your end step, create three 1/1 white Cat creature tokens with lifelink."
public AjaniAdversaryOfTyrantsEmblem() {

View file

@ -15,7 +15,7 @@ import mage.game.permanent.Permanent;
*
* @author spjspj
*/
public class AjaniSteadfastEmblem extends Emblem {
public final class AjaniSteadfastEmblem extends Emblem {
public AjaniSteadfastEmblem() {
setName("Emblem Ajani");

View file

@ -21,7 +21,7 @@ import mage.target.common.TargetAnyTarget;
*
* @author spjspj
*/
public class ArlinnEmbracedByTheMoonEmblem extends Emblem {
public final class ArlinnEmbracedByTheMoonEmblem extends Emblem {
// "Creatures you control have haste and '{T}: This creature deals damage equal to its power to any target.'"
public ArlinnEmbracedByTheMoonEmblem() {

View file

@ -13,7 +13,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class AurraSingBaneOfJediEmblem extends Emblem {
public final class AurraSingBaneOfJediEmblem extends Emblem {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a nontoken creature you control");

View file

@ -12,7 +12,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class ChandraRoaringFlameEmblem extends Emblem {
public final class ChandraRoaringFlameEmblem extends Emblem {
/**
* Emblem with "At the beginning of your upkeep, this emblem deals 3 damage

View file

@ -14,7 +14,7 @@ import mage.target.common.TargetAnyTarget;
*
* @author spjspj
*/
public class ChandraTorchOfDefianceEmblem extends Emblem {
public final class ChandraTorchOfDefianceEmblem extends Emblem {
// You get an emblem with "Whenever you cast a spell, this emblem deals 5 damage to any target."
public ChandraTorchOfDefianceEmblem() {

View file

@ -29,7 +29,7 @@ import mage.target.targetpointer.FixedTargets;
*
* @author spjspj
*/
public class DackFaydenEmblem extends Emblem {
public final class DackFaydenEmblem extends Emblem {
public DackFaydenEmblem() {
this.setName("Emblem Dack");

View file

@ -22,7 +22,7 @@ import mage.target.targetpointer.FixedTarget;
*
* @author spjspj
*/
public class DarettiScrapSavantEmblem extends Emblem {
public final class DarettiScrapSavantEmblem extends Emblem {
// You get an emblem with "Whenever an artifact is put into your graveyard from the battlefield, return that card to the battlefield at the beginning of the next end step."
public DarettiScrapSavantEmblem() {

View file

@ -18,7 +18,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class DomriRadeEmblem extends Emblem {
public final class DomriRadeEmblem extends Emblem {
// "Creatures you control have double strike, trample, hexproof and haste."
public DomriRadeEmblem() {

View file

@ -15,7 +15,7 @@ import mage.players.Player;
*
* @author spjspj
*/
public class DovinBaanEmblem extends Emblem {
public final class DovinBaanEmblem extends Emblem {
public DovinBaanEmblem() {
this.setName("Emblem Dovin");

View file

@ -17,7 +17,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class ElspethKnightErrantEmblem extends Emblem {
public final class ElspethKnightErrantEmblem extends Emblem {
public ElspethKnightErrantEmblem() {
this.setName("Emblem Elspeth");

View file

@ -14,7 +14,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class ElspethSunsChampionEmblem extends Emblem {
public final class ElspethSunsChampionEmblem extends Emblem {
// -7: You get an emblem with "Creatures you control get +2/+2 and have flying."
public ElspethSunsChampionEmblem() {

View file

@ -16,7 +16,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class GarrukApexPredatorEmblem extends Emblem {
public final class GarrukApexPredatorEmblem extends Emblem {
/**
* Emblem with "Whenever a creature attacks you, it gets +5/+5 and gains

View file

@ -16,7 +16,7 @@ import mage.target.common.TargetCardInLibrary;
*
* @author spjspj
*/
public class GarrukCallerOfBeastsEmblem extends Emblem {
public final class GarrukCallerOfBeastsEmblem extends Emblem {
/**
* Emblem: "Whenever you cast a creature spell, you may search your library

View file

@ -12,7 +12,7 @@ import mage.game.command.Emblem;
*
* @author spjspj
*/
public class GideonAllyOfZendikarEmblem extends Emblem {
public final class GideonAllyOfZendikarEmblem extends Emblem {
public GideonAllyOfZendikarEmblem() {
this.setName("Emblem Gideon");

View file

@ -18,7 +18,7 @@ import mage.game.events.GameEvent;
*
* @author spjspj
*/
public class GideonOfTheTrialsEmblem extends Emblem {
public final class GideonOfTheTrialsEmblem extends Emblem {
public GideonOfTheTrialsEmblem() {
this.setName("Emblem - Gideon");

View file

@ -12,7 +12,7 @@ import mage.game.command.Emblem;
*
* @author LevelX2
*/
public class HuatliRadiantChampionEmblem extends Emblem {
public final class HuatliRadiantChampionEmblem extends Emblem {
public HuatliRadiantChampionEmblem() {
this.setName("Emblem Huatli");

Some files were not shown because too many files have changed in this diff Show more