mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 04:52:07 -08:00
Merge branch 'master' into Zzooouhh-ugl
This commit is contained in:
commit
1655963937
773 changed files with 19669 additions and 1871 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 "";
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
142
Mage/src/main/java/mage/abilities/keyword/JumpStartAbility.java
Normal file
142
Mage/src/main/java/mage/abilities/keyword/JumpStartAbility.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ public class MadnessAbility extends StaticAbility {
|
|||
return new MadnessAbility(this);
|
||||
}
|
||||
|
||||
public static Condition GetCondition() {
|
||||
public static Condition getCondition() {
|
||||
return MadnessCondition.instance;
|
||||
}
|
||||
|
||||
|
|
|
|||
56
Mage/src/main/java/mage/abilities/keyword/MentorAbility.java
Normal file
56
Mage/src/main/java/mage/abilities/keyword/MentorAbility.java
Normal 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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<>();
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue