mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 05:22:02 -08:00
Merge branch 'copy_constructor_watchers' of https://github.com/magefree/mage into copy_constructor_watchers
This commit is contained in:
commit
e8303d551d
173 changed files with 5472 additions and 2993 deletions
|
|
@ -53,6 +53,10 @@ public class MageObjectReference implements Comparable<MageObjectReference>, Ser
|
|||
|
||||
public MageObjectReference(UUID sourceId, Game game) {
|
||||
this.sourceId = sourceId;
|
||||
if (sourceId == null) {
|
||||
throw new IllegalArgumentException("MageObjectReference contains nullable sourceId");
|
||||
}
|
||||
|
||||
MageObject mageObject = game.getObject(sourceId);
|
||||
if (mageObject != null) {
|
||||
this.zoneChangeCounter = mageObject.getZoneChangeCounter(game);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
|
|
@ -9,15 +9,21 @@ import mage.constants.Zone;
|
|||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Plopman
|
||||
*/
|
||||
public class CastCommanderAbility extends SpellAbility {
|
||||
|
||||
public CastCommanderAbility(Card card) {
|
||||
super(card.getManaCost(), card.getName(), Zone.COMMAND, SpellAbilityType.BASE);
|
||||
this.costs = card.getSpellAbility().getCosts().copy();
|
||||
this.timing = TimingRule.SORCERY;
|
||||
if (card.getSpellAbility() != null) {
|
||||
this.getCosts().addAll(card.getSpellAbility().getCosts().copy());
|
||||
this.getEffects().addAll(card.getSpellAbility().getEffects().copy());
|
||||
this.getTargets().addAll(card.getSpellAbility().getTargets().copy());
|
||||
this.timing = card.getSpellAbility().getTiming();
|
||||
} else {
|
||||
this.costs = new CostsImpl<>();
|
||||
this.timing = TimingRule.SORCERY;
|
||||
}
|
||||
this.usesStack = true;
|
||||
this.controllerId = card.getOwnerId();
|
||||
this.sourceId = card.getId();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
|
|
@ -45,6 +44,7 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility
|
|||
this.text = ability.text;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
this.onlyOpponents = ability.onlyOpponents;
|
||||
this.orPlaneswalker = ability.orPlaneswalker;
|
||||
}
|
||||
|
||||
public DealsCombatDamageToAPlayerTriggeredAbility setOrPlaneswalker(boolean orPlaneswalker) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
|
|
@ -18,8 +14,11 @@ import mage.players.Player;
|
|||
import mage.target.TargetPermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX
|
||||
*/
|
||||
public class RemoveCounterCost extends CostImpl {
|
||||
|
|
@ -102,10 +101,6 @@ public class RemoveCounterCost extends CostImpl {
|
|||
new StringBuilder("Remove how many counters from ").append(permanent.getIdName()).toString(), game);
|
||||
}
|
||||
permanent.removeCounters(counterName, numberOfCountersSelected, game);
|
||||
if (permanent.getCounters(game).getCount(counterName) == 0) {
|
||||
// this removes only the item with number = 0 from the collection
|
||||
permanent.getCounters(game).removeCounter(counterName);
|
||||
}
|
||||
countersRemoved += numberOfCountersSelected;
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(new StringBuilder(controller.getLogName())
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
package mage.abilities.decorator;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.Condition;
|
||||
|
|
@ -11,11 +7,14 @@ import mage.abilities.condition.FixedCondition;
|
|||
import mage.abilities.condition.LockedInCondition;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.DependencyType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Adds condition to {@link ContinuousEffect}. Acts as decorator.
|
||||
|
|
@ -48,6 +47,18 @@ public class ConditionalContinuousEffect extends ContinuousEffectImpl {
|
|||
this.otherwiseEffect = otherwiseEffect;
|
||||
this.baseCondition = condition;
|
||||
this.staticText = text;
|
||||
|
||||
// checks for compatibility
|
||||
EffectType needType = EffectType.CONTINUOUS;
|
||||
if (effect != null && !effect.getEffectType().equals(needType)) {
|
||||
Assert.fail("ConditionalContinuousEffect supports only " + needType.toString() + " but found " + effect.getEffectType().toString());
|
||||
}
|
||||
if (otherwiseEffect != null && !otherwiseEffect.getEffectType().equals(needType)) {
|
||||
Assert.fail("ConditionalContinuousEffect supports only " + needType.toString() + " but found " + effect.getEffectType().toString());
|
||||
}
|
||||
if (effect != null && otherwiseEffect != null && !effect.getEffectType().equals(otherwiseEffect.getEffectType())) {
|
||||
Assert.fail("ConditionalContinuousEffect must be same but found " + effect.getEffectType().toString() + " and " + otherwiseEffect.getEffectType().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public ConditionalContinuousEffect(final ConditionalContinuousEffect effect) {
|
||||
|
|
@ -68,6 +79,7 @@ public class ConditionalContinuousEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
if (baseCondition instanceof LockedInCondition) {
|
||||
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
package mage.abilities.decorator;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.effects.CostModificationEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class ConditionalCostModificationEffect extends CostModificationEffectImpl {
|
||||
|
||||
protected CostModificationEffect effect;
|
||||
protected CostModificationEffect otherwiseEffect;
|
||||
protected Condition condition;
|
||||
protected boolean conditionState;
|
||||
|
||||
public ConditionalCostModificationEffect(CostModificationEffect effect, Condition condition, String text) {
|
||||
this(effect, condition, null, text);
|
||||
}
|
||||
|
||||
public ConditionalCostModificationEffect(CostModificationEffect effect, Condition condition, CostModificationEffect otherwiseEffect,
|
||||
String text) {
|
||||
super(effect.getDuration(), effect.getOutcome(), effect.getModificationType());
|
||||
this.effect = effect;
|
||||
this.condition = condition;
|
||||
this.otherwiseEffect = otherwiseEffect;
|
||||
if (text != null) {
|
||||
this.setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
public ConditionalCostModificationEffect(final ConditionalCostModificationEffect effect) {
|
||||
super(effect);
|
||||
this.effect = (CostModificationEffect) effect.effect.copy();
|
||||
if (effect.otherwiseEffect != null) {
|
||||
this.otherwiseEffect = (CostModificationEffect) effect.otherwiseEffect.copy();
|
||||
}
|
||||
this.condition = effect.condition;
|
||||
this.conditionState = effect.conditionState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDiscarded() {
|
||||
return effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
conditionState = condition.apply(game, source);
|
||||
if (conditionState) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
return effect.apply(game, source, abilityToModify);
|
||||
} else if (otherwiseEffect != null) {
|
||||
otherwiseEffect.setTargetPointer(this.targetPointer);
|
||||
return otherwiseEffect.apply(game, source, abilityToModify);
|
||||
}
|
||||
if (!conditionState && effect.getDuration() == Duration.OneUse) {
|
||||
used = true;
|
||||
}
|
||||
if (!conditionState && effect.getDuration() == Duration.Custom) {
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
conditionState = condition.apply(game, source);
|
||||
if (conditionState) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
return effect.applies(abilityToModify, source, game);
|
||||
} else if (otherwiseEffect != null) {
|
||||
otherwiseEffect.setTargetPointer(this.targetPointer);
|
||||
return otherwiseEffect.applies(abilityToModify, source, game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConditionalCostModificationEffect copy() {
|
||||
return new ConditionalCostModificationEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
package mage.abilities.decorator;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.FixedCondition;
|
||||
import mage.abilities.condition.LockedInCondition;
|
||||
import mage.abilities.effects.PreventionEffect;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class ConditionalPreventionEffect extends PreventionEffectImpl {
|
||||
|
||||
protected PreventionEffect effect;
|
||||
protected PreventionEffect otherwiseEffect;
|
||||
protected Condition baseCondition;
|
||||
protected Condition condition;
|
||||
protected boolean conditionState;
|
||||
protected boolean initDone = false;
|
||||
|
||||
public ConditionalPreventionEffect(PreventionEffect effect, Condition condition, String text) {
|
||||
this(effect, null, condition, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only use this if both effects have the same layers
|
||||
*
|
||||
* @param effect
|
||||
* @param otherwiseEffect
|
||||
* @param condition
|
||||
* @param text
|
||||
*/
|
||||
public ConditionalPreventionEffect(PreventionEffect effect, PreventionEffect otherwiseEffect, Condition condition, String text) {
|
||||
super(effect.getDuration());
|
||||
this.effect = effect;
|
||||
this.otherwiseEffect = otherwiseEffect;
|
||||
this.baseCondition = condition;
|
||||
this.staticText = text;
|
||||
}
|
||||
|
||||
public ConditionalPreventionEffect(final ConditionalPreventionEffect effect) {
|
||||
super(effect);
|
||||
this.effect = (PreventionEffect) effect.effect.copy();
|
||||
if (effect.otherwiseEffect != null) {
|
||||
this.otherwiseEffect = (PreventionEffect) effect.otherwiseEffect.copy();
|
||||
}
|
||||
this.condition = effect.condition; // TODO: checks conditional copy -- it's can be usefull for memory leaks fix?
|
||||
this.conditionState = effect.conditionState;
|
||||
this.baseCondition = effect.baseCondition;
|
||||
this.initDone = effect.initDone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDiscarded() {
|
||||
return this.discarded || effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
if (baseCondition instanceof LockedInCondition) {
|
||||
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
|
||||
} else {
|
||||
condition = baseCondition;
|
||||
}
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
effect.init(source, game);
|
||||
if (otherwiseEffect != null) {
|
||||
otherwiseEffect.setTargetPointer(this.targetPointer);
|
||||
otherwiseEffect.init(source, game);
|
||||
}
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
if (conditionState) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
return effect.replaceEvent(event, source, game);
|
||||
} else if (otherwiseEffect != null) {
|
||||
otherwiseEffect.setTargetPointer(this.targetPointer);
|
||||
return otherwiseEffect.replaceEvent(event, source, game);
|
||||
}
|
||||
|
||||
if (!conditionState && effect.getDuration() == Duration.OneUse) {
|
||||
used = true;
|
||||
}
|
||||
if (!conditionState && effect.getDuration() == Duration.Custom) {
|
||||
this.discard();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return effect.checksEventType(event, game)
|
||||
|| (otherwiseEffect != null && otherwiseEffect.checksEventType(event, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!initDone) { // if simpleStaticAbility, init won't be called
|
||||
init(source, game);
|
||||
}
|
||||
conditionState = condition.apply(game, source);
|
||||
if (conditionState) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
return effect.applies(event, source, game);
|
||||
} else if (otherwiseEffect != null) {
|
||||
otherwiseEffect.setTargetPointer(this.targetPointer);
|
||||
return otherwiseEffect.applies(event, source, game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if ((staticText == null || staticText.isEmpty()) && this.effect != null) { // usefull for conditional night/day card abilities
|
||||
return effect.getText(mode);
|
||||
}
|
||||
return staticText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConditionalPreventionEffect copy() {
|
||||
return new ConditionalPreventionEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.abilities.decorator;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.FixedCondition;
|
||||
|
|
@ -12,12 +10,13 @@ import mage.constants.EffectType;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class ConditionalRequirementEffect extends RequirementEffect {
|
||||
public class ConditionalRequirementEffect extends RequirementEffect {
|
||||
|
||||
protected RequirementEffect effect;
|
||||
protected RequirementEffect otherwiseEffect;
|
||||
|
|
@ -27,7 +26,14 @@ public class ConditionalRequirementEffect extends RequirementEffect {
|
|||
protected boolean initDone = false;
|
||||
|
||||
public ConditionalRequirementEffect(RequirementEffect effect, Condition condition) {
|
||||
this(Duration.WhileOnBattlefield, effect, condition, null, false);
|
||||
this(effect, condition, null);
|
||||
}
|
||||
|
||||
public ConditionalRequirementEffect(RequirementEffect effect, Condition condition, String text) {
|
||||
this(effect.getDuration(), effect, condition, null, false);
|
||||
if (text != null) {
|
||||
setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
public ConditionalRequirementEffect(Duration duration, RequirementEffect effect, Condition condition, RequirementEffect otherwiseEffect, boolean lockedInCondition) {
|
||||
|
|
@ -75,7 +81,7 @@ public class ConditionalRequirementEffect extends RequirementEffect {
|
|||
conditionState = condition.apply(game, source);
|
||||
if (conditionState) {
|
||||
effect.setTargetPointer(this.targetPointer);
|
||||
return effect.applies(permanent, source,game);
|
||||
return effect.applies(permanent, source, game);
|
||||
} else if (otherwiseEffect != null) {
|
||||
otherwiseEffect.setTargetPointer(this.targetPointer);
|
||||
return otherwiseEffect.applies(permanent, source, game);
|
||||
|
|
@ -138,7 +144,7 @@ public class ConditionalRequirementEffect extends RequirementEffect {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ConditionalRequirementEffect copy() {
|
||||
return new ConditionalRequirementEffect(this);
|
||||
|
|
|
|||
|
|
@ -22,14 +22,25 @@ public class ConditionalRestrictionEffect extends RestrictionEffect {
|
|||
protected boolean initDone = false;
|
||||
|
||||
public ConditionalRestrictionEffect(RestrictionEffect effect, Condition condition) {
|
||||
this(Duration.WhileOnBattlefield, effect, condition, null);
|
||||
this(effect, condition, null);
|
||||
}
|
||||
|
||||
public ConditionalRestrictionEffect(RestrictionEffect effect, Condition condition, String text) {
|
||||
this(effect.getDuration(), effect, condition, null, text);
|
||||
}
|
||||
|
||||
public ConditionalRestrictionEffect(Duration duration, RestrictionEffect effect, Condition condition, RestrictionEffect otherwiseEffect) {
|
||||
this(duration, effect, condition, otherwiseEffect, null);
|
||||
}
|
||||
|
||||
public ConditionalRestrictionEffect(Duration duration, RestrictionEffect effect, Condition condition, RestrictionEffect otherwiseEffect, String text) {
|
||||
super(duration);
|
||||
this.effect = effect;
|
||||
this.baseCondition = condition;
|
||||
this.otherwiseEffect = otherwiseEffect;
|
||||
if (text != null) {
|
||||
this.setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
public ConditionalRestrictionEffect(final ConditionalRestrictionEffect effect) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package mage.abilities.dynamicvalue.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public enum PermanentsYouControlCount implements DynamicValue {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
return game.getBattlefield().count(StaticFilters.FILTER_CONTROLLED_PERMANENT, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermanentsYouControlCount copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "permanents you control";
|
||||
}
|
||||
}
|
||||
|
|
@ -311,14 +311,6 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
}
|
||||
}
|
||||
return dependentToEffects;
|
||||
/*
|
||||
return allEffectsInLayer.stream()
|
||||
.filter(effect -> effect.getDependencyTypes().contains(dependendToTypes))
|
||||
.map(Effect::getId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
}
|
||||
return new HashSet<>();*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ public class ContinuousEffects implements Serializable {
|
|||
replaceEffects.put(effect, applicableAbilities);
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator<PreventionEffect> iterator = preventionEffects.iterator(); iterator.hasNext(); ) {
|
||||
PreventionEffect effect = iterator.next();
|
||||
if (!effect.checksEventType(event, game)) {
|
||||
|
|
@ -394,6 +395,7 @@ public class ContinuousEffects implements Serializable {
|
|||
replaceEffects.put(effect, applicableAbilities);
|
||||
}
|
||||
}
|
||||
|
||||
return replaceEffects;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -70,8 +69,8 @@ public class PreventDamageToAttachedEffect extends PreventionEffectImpl {
|
|||
}
|
||||
sb.append("damage to ");
|
||||
sb.append(attachmentType.verb());
|
||||
sb.append("creature, prevent ").append(amountToPrevent);;
|
||||
sb.append("of that damage");
|
||||
sb.append(" creature, prevent ").append(amountToPrevent);;
|
||||
sb.append(" of that damage");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
|
@ -21,7 +15,6 @@ import java.util.Set;
|
|||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*
|
||||
*/
|
||||
public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
||||
|
||||
|
|
@ -29,13 +22,19 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
protected String theyAreStillType;
|
||||
private final FilterPermanent filter;
|
||||
private boolean loseColor = true;
|
||||
protected boolean loseName = false;
|
||||
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor) {
|
||||
this(token, theyAreStillType, filter, duration, loseColor, false);
|
||||
}
|
||||
|
||||
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
|
||||
super(duration, Outcome.BecomeCreature);
|
||||
this.token = token;
|
||||
this.theyAreStillType = theyAreStillType;
|
||||
this.filter = filter;
|
||||
this.loseColor = loseColor;
|
||||
this.loseName = loseName;
|
||||
}
|
||||
|
||||
public BecomesCreatureAllEffect(final BecomesCreatureAllEffect effect) {
|
||||
|
|
@ -44,6 +43,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
this.theyAreStillType = effect.theyAreStillType;
|
||||
this.filter = effect.filter.copy();
|
||||
this.loseColor = effect.loseColor;
|
||||
this.loseName = effect.loseName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -65,30 +65,47 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Set<Permanent> affectedPermanents = new HashSet<>();
|
||||
if (this.affectedObjectsSet) {
|
||||
for(MageObjectReference ref : affectedObjectList) {
|
||||
for (MageObjectReference ref : affectedObjectList) {
|
||||
affectedPermanents.add(ref.getPermanent(game));
|
||||
}
|
||||
} else {
|
||||
affectedPermanents = new HashSet<>(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
|
||||
}
|
||||
|
||||
for(Permanent permanent : affectedPermanents) {
|
||||
for (Permanent permanent : affectedPermanents) {
|
||||
if (permanent != null) {
|
||||
switch (layer) {
|
||||
case TextChangingEffects_3:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (loseName) {
|
||||
permanent.setName(token.getName());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (!token.getCardType().isEmpty()) {
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.addCardType(t);
|
||||
if (theyAreStillType != null) {
|
||||
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
|
||||
permanent.getSubtype(game).addAll(token.getSubtype(game));
|
||||
} else {
|
||||
for (SubType t : token.getSubtype(game)) {
|
||||
if (!permanent.hasSubtype(t, game)) {
|
||||
permanent.getSubtype(game).add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (theyAreStillType == null) {
|
||||
permanent.getSubtype(game).clear();
|
||||
|
||||
for (SuperType t : token.getSuperType()) {
|
||||
if (!permanent.getSuperType().contains(t)) {
|
||||
permanent.addSuperType(t);
|
||||
}
|
||||
}
|
||||
if (!token.getSubtype(game).isEmpty()) {
|
||||
permanent.getSubtype(game).addAll(token.getSubtype(game));
|
||||
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -141,7 +158,11 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4;
|
||||
return layer == Layer.PTChangingEffects_7
|
||||
|| layer == Layer.AbilityAddingRemovingEffects_6
|
||||
|| layer == Layer.ColorChangingEffects_5
|
||||
|| layer == Layer.TypeChangingEffects_4
|
||||
|| layer == Layer.TextChangingEffects_3;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -69,30 +69,34 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (loseAllAbilities) {
|
||||
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
|
||||
permanent.getSubtype(game).addAll(token.getSubtype(game));
|
||||
} else {
|
||||
if (!token.getSubtype(game).isEmpty()) {
|
||||
for (SubType subtype : token.getSubtype(game)) {
|
||||
if (!permanent.hasSubtype(subtype, game)) {
|
||||
permanent.getSubtype(game).add(subtype);
|
||||
}
|
||||
for (SubType t : token.getSubtype(game)) {
|
||||
if (!permanent.hasSubtype(t, game)) {
|
||||
permanent.getSubtype(game).add(t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!token.getCardType().isEmpty()) {
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
|
||||
for (SuperType t : token.getSuperType()) {
|
||||
if (!permanent.getSuperType().contains(t)) {
|
||||
permanent.addSuperType(t);
|
||||
}
|
||||
}
|
||||
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ColorChangingEffects_5:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (loseAllAbilities) {
|
||||
|
|
@ -107,6 +111,7 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
if (loseAllAbilities) {
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ public class UntapAllDuringEachOtherPlayersUntapStepEffect extends ContinuousEff
|
|||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Boolean applied = (Boolean) game.getState().getValue(source.getSourceId() + "applied");
|
||||
if (applied == null) {
|
||||
applied = Boolean.FALSE;
|
||||
}
|
||||
if (!applied && layer == Layer.RulesEffects) {
|
||||
if (!source.isControlledBy(game.getActivePlayerId()) && game.getStep().getType() == PhaseStep.UNTAP) {
|
||||
game.getState().setValue(source.getSourceId() + "applied", true);
|
||||
if (layer == Layer.RulesEffects && game.getStep().getType() == PhaseStep.UNTAP && !source.isControlledBy(game.getActivePlayerId())) {
|
||||
Integer appliedTurn = (Integer) game.getState().getValue(source.getSourceId() + "appliedTurn");
|
||||
if (appliedTurn == null) {
|
||||
appliedTurn = 0;
|
||||
}
|
||||
if (appliedTurn < game.getTurnNum()) {
|
||||
game.getState().setValue(source.getSourceId() + "appliedTurn", game.getTurnNum());
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
boolean untap = true;
|
||||
for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).keySet()) {
|
||||
|
|
@ -50,10 +50,6 @@ public class UntapAllDuringEachOtherPlayersUntapStepEffect extends ContinuousEff
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (applied && layer == Layer.RulesEffects) {
|
||||
if (game.getStep().getType() == PhaseStep.END_TURN) {
|
||||
game.getState().setValue(source.getSourceId() + "applied", false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.filter.common.FilterPermanentOrPlayerWithCounter;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetPermanentOrPlayerWithCounter;
|
||||
import mage.target.common.TargetPermanentOrPlayer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -47,7 +48,7 @@ public class ProliferateEffect extends OneShotEffect {
|
|||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Target target = new TargetPermanentOrPlayerWithCounter(0, Integer.MAX_VALUE, true);
|
||||
Target target = new TargetPermanentOrPlayer(0, Integer.MAX_VALUE, new FilterPermanentOrPlayerWithCounter(), true);
|
||||
Map<String, Serializable> options = new HashMap<>();
|
||||
options.put("UI.right.btn.text", "Done");
|
||||
controller.choose(Outcome.Benefit, target, source.getSourceId(), game, options);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
|
|||
Cards revealedCards = new CardsImpl();
|
||||
numberToReveal = Math.min(player.getHand().size(), numberToReveal);
|
||||
if (player.getHand().size() > numberToReveal) {
|
||||
TargetCardInHand chosenCards = new TargetCardInHand(numberToReveal, numberToReveal, new FilterCard("card in " + player.getLogName() + "'s hand"));
|
||||
TargetCardInHand chosenCards = new TargetCardInHand(numberToReveal, numberToReveal, new FilterCard("card in " + player.getName() + "'s hand"));
|
||||
chosenCards.setNotTarget(true);
|
||||
if (chosenCards.canChoose(player.getId(), game) && player.chooseTarget(Outcome.Discard, player.getHand(), chosenCards, source, game)) {
|
||||
if (!chosenCards.getTargets().isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package mage.abilities.effects.keyword;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
|
@ -19,10 +21,10 @@ public class AdaptEffect extends OneShotEffect {
|
|||
public AdaptEffect(int adaptNumber) {
|
||||
super(Outcome.BoostCreature);
|
||||
this.adaptNumber = adaptNumber;
|
||||
staticText = "Adapt " + adaptNumber +
|
||||
" <i>(If this creature has no +1/+1 counters on it, put " +
|
||||
CardUtil.numberToText(adaptNumber) + " +1/+1 counter" +
|
||||
(adaptNumber > 1 ? "s" : "") + " on it.)</i>";
|
||||
staticText = "Adapt " + adaptNumber
|
||||
+ " <i>(If this creature has no +1/+1 counters on it, put "
|
||||
+ CardUtil.numberToText(adaptNumber) + " +1/+1 counter"
|
||||
+ (adaptNumber > 1 ? "s" : "") + " on it.)</i>";
|
||||
}
|
||||
|
||||
private AdaptEffect(final AdaptEffect effect) {
|
||||
|
|
@ -37,7 +39,15 @@ public class AdaptEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
// Verify source object did not change zone and is on the battlefield
|
||||
MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
|
||||
if (sourceObject == null) {
|
||||
if (game.getState().getZone(source.getSourceId()).equals(Zone.BATTLEFIELD)
|
||||
&& source.getSourceObjectZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(source.getSourceId())) {
|
||||
sourceObject = game.getPermanent(source.getSourceId());
|
||||
}
|
||||
}
|
||||
Permanent permanent = ((Permanent) sourceObject);
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -48,7 +58,8 @@ public class AdaptEffect extends OneShotEffect {
|
|||
if (game.replaceEvent(event)) {
|
||||
return false;
|
||||
}
|
||||
if (permanent.getCounters(game).getCount(CounterType.P1P1) == 0 || event.getFlag()) {
|
||||
if (permanent.getCounters(game).getCount(CounterType.P1P1) == 0
|
||||
|| event.getFlag()) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(event.getAmount()), source, game);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package mage.abilities.hint.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsYouControlCount;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public enum PermanentsYouControlHint implements Hint {
|
||||
|
||||
instance;
|
||||
private static final Hint hint = new ValueHint("Permanents you control", PermanentsYouControlCount.instance);
|
||||
|
||||
@Override
|
||||
public String getText(Game game, Ability ability) {
|
||||
return hint.getText(game, ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hint copy() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
@ -690,27 +690,33 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
sourceId = source.getSourceId();
|
||||
}
|
||||
}
|
||||
GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount());
|
||||
countersEvent.setAppliedEffects(appliedEffects);
|
||||
countersEvent.setFlag(isEffect);
|
||||
if (!game.replaceEvent(countersEvent)) {
|
||||
int amount = countersEvent.getAmount();
|
||||
GameEvent addingAllEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount());
|
||||
addingAllEvent.setAppliedEffects(appliedEffects);
|
||||
addingAllEvent.setFlag(isEffect);
|
||||
if (!game.replaceEvent(addingAllEvent)) {
|
||||
int amount = addingAllEvent.getAmount();
|
||||
boolean isEffectFlag = addingAllEvent.getFlag();
|
||||
int finalAmount = amount;
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Counter eventCounter = counter.copy();
|
||||
eventCounter.remove(eventCounter.getCount() - 1);
|
||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTER, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1);
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
GameEvent addingOneEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTER, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1);
|
||||
addingOneEvent.setAppliedEffects(appliedEffects);
|
||||
addingOneEvent.setFlag(isEffectFlag);
|
||||
if (!game.replaceEvent(addingOneEvent)) {
|
||||
getCounters(game).addCounter(eventCounter);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1));
|
||||
GameEvent addedOneEvent = GameEvent.getEvent(GameEvent.EventType.COUNTER_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1);
|
||||
addedOneEvent.setFlag(addingOneEvent.getFlag());
|
||||
game.fireEvent(addedOneEvent);
|
||||
} else {
|
||||
finalAmount--;
|
||||
returnCode = false;
|
||||
}
|
||||
}
|
||||
if (finalAmount > 0) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), amount));
|
||||
GameEvent addedAllEvent = GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), amount);
|
||||
addedAllEvent.setFlag(isEffectFlag);
|
||||
game.fireEvent(addedAllEvent);
|
||||
}
|
||||
} else {
|
||||
returnCode = false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards.decks.exporter;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import mage.cards.decks.DeckFileFilter;
|
||||
|
|
@ -13,9 +14,11 @@ import java.util.*;
|
|||
*/
|
||||
public class MtgArenaDeckExporter extends DeckExporter {
|
||||
|
||||
private final String ext = "mtga";
|
||||
private final String description = "MTG Arena's deck format (*.mtga)";
|
||||
private final FileFilter fileFilter = new DeckFileFilter(ext, description);
|
||||
private static final String ext = "mtga";
|
||||
private static final String description = "MTG Arena's deck format (*.mtga)";
|
||||
private static final FileFilter fileFilter = new DeckFileFilter(ext, description);
|
||||
|
||||
private static final Map<String, String> SET_CODE_REPLACEMENTS = ImmutableMap.of("DOM", "DAR");
|
||||
|
||||
@Override
|
||||
public void writeDeck(PrintWriter out, DeckCardLists deck) {
|
||||
|
|
@ -33,7 +36,9 @@ public class MtgArenaDeckExporter extends DeckExporter {
|
|||
private List<String> prepareCardsList(List<DeckCardInfo> sourceCards, Map<String, Integer> amount, String prefix) {
|
||||
List<String> res = new ArrayList<>();
|
||||
for (DeckCardInfo card : sourceCards) {
|
||||
String name = card.getCardName() + " (" + card.getSetCode().toUpperCase(Locale.ENGLISH) + ") " + card.getCardNum();
|
||||
String setCode = card.getSetCode().toUpperCase(Locale.ENGLISH);
|
||||
setCode = SET_CODE_REPLACEMENTS.getOrDefault(setCode, setCode);
|
||||
String name = card.getCardName() + " (" + setCode + ") " + card.getCardNum();
|
||||
String code = prefix + name;
|
||||
int curAmount = amount.getOrDefault(code, 0);
|
||||
if (curAmount == 0) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public class MtgArenaDeckExporterTest {
|
|||
deck.getCards().add(new DeckCardInfo("Plains", "2", "RNA", 3));
|
||||
deck.getCards().add(new DeckCardInfo("Plains", "2", "RNA", 5)); // must combine
|
||||
deck.getCards().add(new DeckCardInfo("Mountain", "3", "RNA", 1));
|
||||
deck.getCards().add(new DeckCardInfo("Goblin Chainwhirler", "129", "DOM", 4));
|
||||
deck.getSideboard().add(new DeckCardInfo("Island", "1", "RNA", 2));
|
||||
deck.getSideboard().add(new DeckCardInfo("Island", "1", "RNA", 5)); // must combine
|
||||
deck.getSideboard().add(new DeckCardInfo("Mountain", "2", "RNA", 3));
|
||||
|
|
@ -30,6 +31,7 @@ public class MtgArenaDeckExporterTest {
|
|||
assertEquals("2 Forest (RNA) 1" + System.lineSeparator() +
|
||||
"8 Plains (RNA) 2" + System.lineSeparator() +
|
||||
"1 Mountain (RNA) 3" + System.lineSeparator() +
|
||||
"4 Goblin Chainwhirler (DAR) 129" + System.lineSeparator() +
|
||||
System.lineSeparator() +
|
||||
"7 Island (RNA) 1" + System.lineSeparator() +
|
||||
"3 Mountain (RNA) 2" + System.lineSeparator(),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
|
||||
|
||||
package mage.filter.common;
|
||||
|
||||
import mage.MageItem;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageItem;
|
||||
|
||||
/**
|
||||
* @author nantuko
|
||||
|
|
@ -28,24 +26,24 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer
|
|||
|
||||
@Override
|
||||
public boolean match(MageItem o, Game game) {
|
||||
if (o instanceof Player) {
|
||||
if (((Player)o).getCounters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
} else if (o instanceof Permanent) {
|
||||
if (((Permanent)o).getCounters(game).isEmpty()) {
|
||||
return false;
|
||||
if (super.match(o, game)) {
|
||||
if (o instanceof Player) {
|
||||
return !((Player) o).getCounters().isEmpty();
|
||||
} else if (o instanceof Permanent) {
|
||||
return !((Permanent) o).getCounters(game).isEmpty();
|
||||
}
|
||||
}
|
||||
return super.match(o, game);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(MageItem o, UUID sourceId, UUID playerId, Game game) {
|
||||
if (o instanceof Player) {
|
||||
return playerFilter.match((Player) o, sourceId, playerId, game);
|
||||
} else if (o instanceof Permanent) {
|
||||
return permanentFilter.match((Permanent) o, sourceId, playerId, game);
|
||||
if (super.match(o, sourceId, playerId, game)) {
|
||||
if (o instanceof Player) {
|
||||
return !((Player) o).getCounters().isEmpty();
|
||||
} else if (o instanceof Permanent) {
|
||||
return !((Permanent) o).getCounters(game).isEmpty();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ public interface Game extends MageItem, Serializable {
|
|||
// game cheats (for tests only)
|
||||
void cheat(UUID ownerId, Map<Zone, String> commands);
|
||||
|
||||
void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard);
|
||||
void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command);
|
||||
|
||||
// controlling the behaviour of replacement effects while permanents entering the battlefield
|
||||
void setScopeRelevant(boolean scopeRelevant);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
//Move commander to command zone
|
||||
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
|
||||
Player player = getPlayer(playerId);
|
||||
|
|
@ -49,7 +48,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
for (UUID commanderId : player.getCommandersIds()) {
|
||||
Card commander = this.getCard(commanderId);
|
||||
if (commander != null) {
|
||||
initCommander(commander, ability, player);
|
||||
initCommander(commander, player);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -57,20 +56,20 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
Card commander = this.getCard(player.getSideboard().iterator().next());
|
||||
if (commander != null) {
|
||||
player.addCommanderId(commander.getId());
|
||||
initCommander(commander, ability, player);
|
||||
initCommander(commander, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.getState().addAbility(ability, null);
|
||||
super.init(choosingPlayerId);
|
||||
if (startingPlayerSkipsDraw) {
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
}
|
||||
}
|
||||
|
||||
private void initCommander(Card commander, Ability ability, Player player) {
|
||||
public void initCommander(Card commander, Player player) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
commander.moveToZone(Zone.COMMAND, null, this, true);
|
||||
commander.getAbilities().setControllerId(player.getId());
|
||||
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
|
||||
|
|
@ -79,6 +78,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), checkCommanderDamage);
|
||||
getState().addWatcher(watcher);
|
||||
watcher.addCardInfoToCommander(this);
|
||||
this.getState().addAbility(ability, null);
|
||||
}
|
||||
|
||||
//20130711
|
||||
|
|
|
|||
|
|
@ -2851,26 +2851,39 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard) {
|
||||
public void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command) {
|
||||
Player player = getPlayer(ownerId);
|
||||
if (player != null) {
|
||||
loadCards(ownerId, library);
|
||||
loadCards(ownerId, hand);
|
||||
loadCards(ownerId, battlefield);
|
||||
loadCards(ownerId, graveyard);
|
||||
loadCards(ownerId, command);
|
||||
|
||||
for (Card card : library) {
|
||||
player.getLibrary().putOnTop(card, this);
|
||||
}
|
||||
|
||||
for (Card card : hand) {
|
||||
card.setZone(Zone.HAND, this);
|
||||
player.getHand().add(card);
|
||||
}
|
||||
|
||||
for (Card card : graveyard) {
|
||||
card.setZone(Zone.GRAVEYARD, this);
|
||||
player.getGraveyard().add(card);
|
||||
}
|
||||
|
||||
// as commander (only commander games, look at init code in GameCommanderImpl)
|
||||
if (this instanceof GameCommanderImpl) {
|
||||
for (Card card : command) {
|
||||
player.addCommanderId(card.getId());
|
||||
// no needs in initCommander call -- it's uses on game startup (init)
|
||||
}
|
||||
} else if (!command.isEmpty()) {
|
||||
throw new IllegalArgumentException("Command zone supports in commander test games");
|
||||
}
|
||||
|
||||
// warning, permanents go to battlefield without resolve, continuus effects must be init
|
||||
for (PermanentCard permanentCard : battlefield) {
|
||||
permanentCard.setZone(Zone.BATTLEFIELD, this);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
|
||||
package mage.game;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
|
@ -21,8 +17,11 @@ import mage.game.turn.TurnMod;
|
|||
import mage.players.Player;
|
||||
import mage.watchers.common.CommanderInfoWatcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JRHerlehy
|
||||
*/
|
||||
public abstract class GameTinyLeadersImpl extends GameImpl {
|
||||
|
|
@ -43,7 +42,6 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
|
|||
|
||||
@Override
|
||||
protected void init(UUID choosingPlayerId) {
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
//Move tiny leader to command zone
|
||||
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
|
||||
Player player = getPlayer(playerId);
|
||||
|
|
@ -55,6 +53,7 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
|
|||
this.loadCards(cards, playerId);
|
||||
player.addCommanderId(commander.getId());
|
||||
commander.moveToZone(Zone.COMMAND, null, this, true);
|
||||
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
|
||||
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
|
||||
ability.addEffect(new CommanderCostModification(commander.getId()));
|
||||
// Commander rule #4 was removed Jan. 18, 2016
|
||||
|
|
@ -63,13 +62,13 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
|
|||
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), false);
|
||||
getState().addWatcher(watcher);
|
||||
watcher.addCardInfoToCommander(this);
|
||||
this.getState().addAbility(ability, null);
|
||||
} else {
|
||||
throw new UnknownError("Commander card could not be created. Name: [" + player.getMatchPlayer().getDeck().getName() + ']');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.getState().addAbility(ability, null);
|
||||
super.init(choosingPlayerId);
|
||||
if (startingPlayerSkipsDraw) {
|
||||
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ public class GameEvent implements Serializable {
|
|||
protected UUID sourceId;
|
||||
protected UUID playerId;
|
||||
protected int amount;
|
||||
// flags:
|
||||
// for counters: event is result of effect (+1 from planeswalkers is cost, not effect)
|
||||
// for combat damage: event is preventable damage
|
||||
protected boolean flag;
|
||||
protected String data;
|
||||
protected Zone zone;
|
||||
|
|
@ -433,6 +436,17 @@ public class GameEvent implements Serializable {
|
|||
this.amount = amount;
|
||||
}
|
||||
|
||||
public void setAmountForCounters(int amount, boolean isEffect) {
|
||||
this.amount = amount;
|
||||
|
||||
// cost event must be "transformed" to effect event, as example:
|
||||
// planeswalker's +1 cost will be affected by Pir, Imaginative Rascal (1 + 1) and applied as effect by Doubling Season (2 * 2)
|
||||
// https://github.com/magefree/mage/issues/5802
|
||||
if (isEffect) {
|
||||
setFlag(true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -909,7 +909,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
if (countersToRemove > getCounters(game).getCount(CounterType.LOYALTY)) {
|
||||
countersToRemove = getCounters(game).getCount(CounterType.LOYALTY);
|
||||
}
|
||||
getCounters(game).removeCounter(CounterType.LOYALTY, countersToRemove);
|
||||
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, game);
|
||||
game.fireEvent(new DamagedPlaneswalkerEvent(objectId, sourceId, controllerId, actualDamage, combat));
|
||||
return actualDamage;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -569,6 +569,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
// set the value for non mana X costs
|
||||
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
|
||||
|
||||
// TODO: rework choose replacement effects to use array, not map (it'a random order now)
|
||||
int chooseReplacementEffect(Map<String, String> abilityMap, Game game);
|
||||
|
||||
TriggeredAbility chooseTriggeredAbility(List<TriggeredAbility> abilities, Game game);
|
||||
|
|
|
|||
|
|
@ -182,7 +182,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
protected final Map<PhaseStep, Step.StepPart> silentPhaseSteps = ImmutableMap.<PhaseStep, Step.StepPart>builder().
|
||||
put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build();
|
||||
|
||||
|
||||
public PlayerImpl(String name, RangeOfInfluence range) {
|
||||
this(UUID.randomUUID());
|
||||
this.name = name;
|
||||
|
|
@ -611,7 +610,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
if (abilities.containsKey(HexproofAbility.getInstance().getId())) {
|
||||
if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game)
|
||||
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, this.getId(), game)) {
|
||||
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, sourceControllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2011,24 +2010,30 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public boolean addCounters(Counter counter, Game game) {
|
||||
boolean returnCode = true;
|
||||
GameEvent countersEvent = GameEvent.getEvent(EventType.ADD_COUNTERS, playerId, null, playerId, counter.getName(), counter.getCount());
|
||||
if (!game.replaceEvent(countersEvent)) {
|
||||
int amount = countersEvent.getAmount();
|
||||
GameEvent addingAllEvent = GameEvent.getEvent(EventType.ADD_COUNTERS, playerId, null, playerId, counter.getName(), counter.getCount());
|
||||
if (!game.replaceEvent(addingAllEvent)) {
|
||||
int amount = addingAllEvent.getAmount();
|
||||
int finalAmount = amount;
|
||||
boolean isEffectFlag = addingAllEvent.getFlag();
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Counter eventCounter = counter.copy();
|
||||
eventCounter.remove(eventCounter.getCount() - 1);
|
||||
GameEvent event = GameEvent.getEvent(EventType.ADD_COUNTER, playerId, null, playerId, counter.getName(), 1);
|
||||
if (!game.replaceEvent(event)) {
|
||||
GameEvent addingOneEvent = GameEvent.getEvent(EventType.ADD_COUNTER, playerId, null, playerId, counter.getName(), 1);
|
||||
addingOneEvent.setFlag(isEffectFlag);
|
||||
if (!game.replaceEvent(addingOneEvent)) {
|
||||
getCounters().addCounter(eventCounter);
|
||||
game.fireEvent(GameEvent.getEvent(EventType.COUNTER_ADDED, playerId, null, playerId, counter.getName(), 1));
|
||||
GameEvent addedOneEvent = GameEvent.getEvent(EventType.COUNTER_ADDED, playerId, null, playerId, counter.getName(), 1);
|
||||
addedOneEvent.setFlag(addingOneEvent.getFlag());
|
||||
game.fireEvent(addedOneEvent);
|
||||
} else {
|
||||
finalAmount--;
|
||||
returnCode = false;
|
||||
}
|
||||
}
|
||||
if (finalAmount > 0) {
|
||||
game.fireEvent(GameEvent.getEvent(EventType.COUNTERS_ADDED, playerId, null, playerId, counter.getName(), amount));
|
||||
GameEvent addedAllEvent = GameEvent.getEvent(EventType.COUNTERS_ADDED, playerId, null, playerId, counter.getName(), amount);
|
||||
addedAllEvent.setFlag(addingAllEvent.getFlag());
|
||||
game.fireEvent(addedAllEvent);
|
||||
}
|
||||
} else {
|
||||
returnCode = false;
|
||||
|
|
|
|||
221
Mage/src/main/java/mage/players/StubPlayer.java
Normal file
221
Mage/src/main/java/mage/players/StubPlayer.java
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
package mage.players;
|
||||
|
||||
import mage.MageItem;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.draft.Draft;
|
||||
import mage.game.match.Match;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.tournament.Tournament;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetAmount;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class StubPlayer extends PlayerImpl implements Player {
|
||||
|
||||
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
|
||||
if (target instanceof TargetPlayer) {
|
||||
for (Player player : game.getPlayers().values()) {
|
||||
if (player.getId().equals(getId()) && target.canTarget(getId(), game)) {
|
||||
target.add(player.getId(), game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
|
||||
cards.getCards(game).stream().map(MageItem::getId).forEach(cardId -> target.add(cardId, game));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
|
||||
if ("cards to PUT on the BOTTOM of your library (Discard for Mulligan)".equals(target.getFilter().getMessage())) {
|
||||
chooseDiscardBottom(game, target.getMinNumberOfTargets(), cards.getCards(game)
|
||||
.stream().map(MageItem::getId).collect(toList())).forEach(cardId -> target.add(cardId, game));
|
||||
} else {
|
||||
UUID cardId = getOnlyElement(cards.getCards(game)).getId();
|
||||
if (chooseScry(game, cardId)) {
|
||||
target.add(cardId, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<UUID> chooseDiscardBottom(Game game, int count, List<UUID> cardIds) {
|
||||
return cardIds.subList(0, count);
|
||||
}
|
||||
|
||||
public boolean chooseScry(Game game, UUID cardId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shuffleLibrary(Ability source, Game game) {
|
||||
|
||||
}
|
||||
|
||||
public StubPlayer(String name, RangeOfInfluence range) {
|
||||
super(name, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abort() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skip() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player copy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean priority(Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseMulligan(Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Choice choice, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playMana(Ability ability, ManaCost unpaid, String promptText, Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int chooseReplacementEffect(Map<String, String> abilityMap, Game game) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriggeredAbility chooseTriggeredAbility(List<TriggeredAbility> abilities, Game game) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode chooseMode(Modes modes, Ability source, Game game) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectAttackers(Game game, UUID attackingPlayerId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectBlockers(Game game, UUID defendingPlayerId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID chooseAttackerOrder(List<Permanent> attacker, Game game) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup, List<UUID> blockerOrder, Game game) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignDamage(int damage, List<UUID> targets, String singleTargetName, UUID sourceId, Game game) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmount(int min, int max, String message, Game game) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sideboard(Match match, Deck deck) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void construct(Tournament tournament, Deck deck) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickCard(List<Card> cards, Deck deck, Draft draft) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ public class Targets extends ArrayList<Target> {
|
|||
if (!canChoose(source.getSourceId(), playerId, game)) {
|
||||
return false;
|
||||
}
|
||||
int state = game.bookmarkState();
|
||||
//int state = game.bookmarkState();
|
||||
while (!isChosen()) {
|
||||
Target target = this.getUnchosen().get(0);
|
||||
UUID targetController = playerId;
|
||||
|
|
@ -93,7 +93,7 @@ public class Targets extends ArrayList<Target> {
|
|||
// Check if there are some rules for targets are violated, if so reset the targets and start again
|
||||
if (this.getUnchosen().isEmpty()
|
||||
&& game.replaceEvent(new GameEvent(GameEvent.EventType.TARGETS_VALID, source.getSourceId(), source.getSourceId(), source.getControllerId()), source)) {
|
||||
game.restoreState(state, "Targets");
|
||||
//game.restoreState(state, "Targets");
|
||||
clearChosen();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,22 @@ package mage.target.common;
|
|||
import mage.filter.common.FilterOpponentOrPlaneswalker;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TargetOpponentOrPlaneswalker extends TargetPermanentOrPlayer {
|
||||
|
||||
public TargetOpponentOrPlaneswalker() {
|
||||
this(1, 1, new FilterOpponentOrPlaneswalker("opponent or planeswalker"), false);
|
||||
}
|
||||
|
||||
public TargetOpponentOrPlaneswalker(int numTargets) {
|
||||
this(numTargets, numTargets, new FilterOpponentOrPlaneswalker(), false);
|
||||
this(1);
|
||||
}
|
||||
|
||||
public TargetOpponentOrPlaneswalker(FilterOpponentOrPlaneswalker filter) {
|
||||
this(1, 1, filter, false);
|
||||
}
|
||||
|
||||
public TargetOpponentOrPlaneswalker(int numTargets) {
|
||||
this(numTargets, numTargets, new FilterOpponentOrPlaneswalker("opponent or planeswalker"), false);
|
||||
}
|
||||
|
||||
public TargetOpponentOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterOpponentOrPlaneswalker filter, boolean notTarget) {
|
||||
super(minNumTargets, maxNumTargets, filter, notTarget);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,26 @@
|
|||
package mage.target.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterPermanentOrPlayer;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetImpl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class TargetPermanentOrPlayer extends TargetImpl {
|
||||
|
||||
protected FilterPermanentOrPlayer filter;
|
||||
protected FilterPermanent filterPermanent;
|
||||
|
||||
public TargetPermanentOrPlayer() {
|
||||
this(1, 1);
|
||||
|
|
@ -46,14 +44,12 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
this.zone = Zone.ALL;
|
||||
this.filter = filter;
|
||||
this.targetName = filter.getMessage();
|
||||
this.filterPermanent = this.filter.getPermanentFilter();
|
||||
this.notTarget = notTarget;
|
||||
}
|
||||
|
||||
public TargetPermanentOrPlayer(final TargetPermanentOrPlayer target) {
|
||||
super(target);
|
||||
this.filter = target.filter.copy();
|
||||
this.filterPermanent = target.filterPermanent.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -61,10 +57,6 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
return filter;
|
||||
}
|
||||
|
||||
public void setFilter(FilterPermanentOrPlayer filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Game game) {
|
||||
Permanent permanent = game.getPermanent(id);
|
||||
|
|
@ -118,7 +110,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
* {@link mage.players.Player} that can be chosen. Should only be used for
|
||||
* Ability targets since this checks for protection, shroud etc.
|
||||
*
|
||||
* @param sourceId - the target event source
|
||||
* @param sourceId - the target event source
|
||||
* @param sourceControllerId - controller of the target event source
|
||||
* @param game
|
||||
* @return - true if enough valid {@link mage.game.permanent.Permanent} or
|
||||
|
|
@ -130,14 +122,14 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
MageObject targetSource = game.getObject(sourceId);
|
||||
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) {
|
||||
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, sourceId, sourceControllerId, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT, sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
|
|
@ -170,7 +162,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (filter.match(permanent, null, sourceControllerId, game) && filter.match(permanent, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
|
|
@ -187,11 +179,11 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
MageObject targetSource = game.getObject(sourceId);
|
||||
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) {
|
||||
if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(player, sourceId, sourceControllerId, game)) {
|
||||
possibleTargets.add(playerId);
|
||||
}
|
||||
}
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterPermanent(), sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if ((notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(permanent, sourceId, sourceControllerId, game)) {
|
||||
possibleTargets.add(permanent.getId());
|
||||
}
|
||||
|
|
@ -204,11 +196,11 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && filter.getPlayerFilter().match(player, game)) {
|
||||
if (player != null && filter.match(player, game)) {
|
||||
possibleTargets.add(playerId);
|
||||
}
|
||||
}
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (filter.match(permanent, null, sourceControllerId, game)) {
|
||||
possibleTargets.add(permanent.getId());
|
||||
}
|
||||
|
|
@ -237,6 +229,6 @@ public class TargetPermanentOrPlayer extends TargetImpl {
|
|||
}
|
||||
|
||||
public FilterPermanent getFilterPermanent() {
|
||||
return filterPermanent.copy();
|
||||
return filter.getPermanentFilter().copy();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
|
||||
package mage.target.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.filter.common.FilterPermanentOrPlayerWithCounter;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import java.util.UUID;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.permanent.CounterPredicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class TargetPermanentOrPlayerWithCounter extends TargetPermanentOrPlayer {
|
||||
|
||||
protected final FilterPermanentOrPlayerWithCounter targetFilter;
|
||||
|
||||
public TargetPermanentOrPlayerWithCounter() {
|
||||
this(1, 1);
|
||||
}
|
||||
|
||||
public TargetPermanentOrPlayerWithCounter(int numTargets) {
|
||||
this(numTargets, numTargets);
|
||||
}
|
||||
|
||||
public TargetPermanentOrPlayerWithCounter(int minNumTargets, int maxNumTargets) {
|
||||
this(minNumTargets, maxNumTargets, false);
|
||||
}
|
||||
|
||||
public TargetPermanentOrPlayerWithCounter(int minNumTargets, int maxNumTargets, boolean notTarget) {
|
||||
super(minNumTargets, maxNumTargets, notTarget);
|
||||
this.targetFilter = new FilterPermanentOrPlayerWithCounter();
|
||||
this.filterPermanent = new FilterPermanent();
|
||||
this.filterPermanent.add(new CounterPredicate(null));
|
||||
this.targetName = targetFilter.getMessage();
|
||||
}
|
||||
|
||||
public TargetPermanentOrPlayerWithCounter(final TargetPermanentOrPlayerWithCounter target) {
|
||||
super(target);
|
||||
this.targetFilter = target.targetFilter.copy();
|
||||
super.setFilter(this.targetFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPermanentOrPlayerWithCounter copy() {
|
||||
return new TargetPermanentOrPlayerWithCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Game game) {
|
||||
Permanent permanent = game.getPermanent(id);
|
||||
if (permanent != null) {
|
||||
if (permanent.getCounters(game).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Player player = game.getPlayer(id);
|
||||
if (player != null) {
|
||||
if (player.getCounters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.canTarget(id, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(id);
|
||||
if (permanent != null) {
|
||||
if (permanent.getCounters(game).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Player player = game.getPlayer(id);
|
||||
if (player != null) {
|
||||
if (player.getCounters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.canTarget(id, source, game);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -37,10 +37,12 @@ public class DragonOnTheBattlefieldWhileSpellWasCastWatcher extends Watcher {
|
|||
// revealed a Dragon card or controlled a Dragon as you cast the spell
|
||||
if (spell != null) {
|
||||
boolean revealedOrOnBattlefield = false;
|
||||
for (Cost cost : spell.getSpellAbility().getCosts()) {
|
||||
if (cost instanceof RevealTargetFromHandCost) {
|
||||
revealedOrOnBattlefield = ((RevealTargetFromHandCost) cost).getNumberRevealedCards() > 0;
|
||||
break;
|
||||
if (spell.getSpellAbility() != null) {
|
||||
for (Cost cost : spell.getSpellAbility().getCosts()) {
|
||||
if (cost instanceof RevealTargetFromHandCost) {
|
||||
revealedOrOnBattlefield = ((RevealTargetFromHandCost) cost).getNumberRevealedCards() > 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!revealedOrOnBattlefield) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue