mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 13:02:06 -08:00
Merge origin/master
Conflicts: Mage.Sets/src/mage/cards/c/CogworkAssembler.java
This commit is contained in:
commit
a175ac3a1d
486 changed files with 6577 additions and 6675 deletions
|
|
@ -30,6 +30,7 @@ package mage.abilities;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.Mana;
|
||||
|
|
@ -76,7 +77,6 @@ import mage.watchers.Watcher;
|
|||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public abstract class AbilityImpl implements Ability {
|
||||
|
|
@ -197,7 +197,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
boolean effectResult = effect.apply(game, this);
|
||||
result &= effectResult;
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (!this.getAbilityType().equals(AbilityType.MANA)) {
|
||||
if (this.getAbilityType() != AbilityType.MANA) {
|
||||
if (!effectResult) {
|
||||
if (this.getSourceId() != null) {
|
||||
MageObject mageObject = game.getObject(this.getSourceId());
|
||||
|
|
@ -267,7 +267,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
* If the player wishes to splice any cards onto the spell (see rule 702.45), he
|
||||
* or she reveals those cards in his or her hand.
|
||||
*/
|
||||
if (this.abilityType.equals(AbilityType.SPELL)) {
|
||||
if (this.abilityType == AbilityType.SPELL) {
|
||||
game.getContinuousEffects().applySpliceEffects(this, game);
|
||||
}
|
||||
|
||||
|
|
@ -290,8 +290,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
// or her intentions to pay any or all of those costs (see rule 601.2e).
|
||||
// A player can't apply two alternative methods of casting or two alternative costs to a single spell.
|
||||
if (!activateAlternateOrAdditionalCosts(sourceObject, noMana, controller, game)) {
|
||||
if (getAbilityType().equals(AbilityType.SPELL)
|
||||
&& ((SpellAbility) this).getSpellAbilityType().equals(SpellAbilityType.FACE_DOWN_CREATURE)) {
|
||||
if (getAbilityType() == AbilityType.SPELL
|
||||
&& ((SpellAbility) this).getSpellAbilityType() == SpellAbilityType.FACE_DOWN_CREATURE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -302,7 +302,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller);
|
||||
String announceString = handleOtherXCosts(game, controller);
|
||||
// For effects from cards like Void Winnower x costs have to be set
|
||||
if (this.getAbilityType().equals(AbilityType.SPELL)
|
||||
if (this.getAbilityType() == AbilityType.SPELL
|
||||
&& game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -325,7 +325,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
// and/or zones become the target of a spell trigger at this point; they'll wait to be put on
|
||||
// the stack until the spell has finished being cast.)
|
||||
|
||||
if (sourceObject != null && !this.getAbilityType().equals(AbilityType.TRIGGERED)) { // triggered abilities check this already in playerImpl.triggerAbility
|
||||
if (sourceObject != null && this.getAbilityType() != AbilityType.TRIGGERED) { // triggered abilities check this already in playerImpl.triggerAbility
|
||||
sourceObject.adjustTargets(this, game);
|
||||
}
|
||||
// Flashback abilities haven't made the choices the underlying spell might need for targeting.
|
||||
|
|
@ -408,7 +408,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
activated = true;
|
||||
// fire if tapped for mana (may only fire now because else costs of ability itself can be payed with mana of abilities that trigger for that event
|
||||
if (this.getAbilityType().equals(AbilityType.MANA)) {
|
||||
if (this.getAbilityType() == AbilityType.MANA) {
|
||||
for (Cost cost : costs) {
|
||||
if (cost instanceof TapSourceCost) {
|
||||
Mana mana = null;
|
||||
|
|
@ -466,10 +466,10 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
// controller specific alternate spell costs
|
||||
if (!noMana && !alternativeCostisUsed) {
|
||||
if (this.getAbilityType().equals(AbilityType.SPELL)
|
||||
if (this.getAbilityType() == AbilityType.SPELL
|
||||
// 117.9a Only one alternative cost can be applied to any one spell as it’s being cast.
|
||||
// So an alternate spell ability can't be paid with Omniscience
|
||||
&& !((SpellAbility) this).getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) {
|
||||
&& ((SpellAbility) this).getSpellAbilityType() != SpellAbilityType.BASE_ALTERNATE) {
|
||||
for (AlternativeSourceCosts alternativeSourceCosts : controller.getAlternativeSourceCosts()) {
|
||||
if (alternativeSourceCosts.isAvailable(this, game)) {
|
||||
if (alternativeSourceCosts.askToActivateAlternativeCosts(this, game)) {
|
||||
|
|
@ -489,10 +489,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
* Handles the setting of non mana X costs
|
||||
*
|
||||
* @param controller
|
||||
*
|
||||
* @param game
|
||||
* @return announce message
|
||||
*
|
||||
*/
|
||||
protected String handleOtherXCosts(Game game, Player controller) {
|
||||
String announceString = null;
|
||||
|
|
@ -873,7 +871,6 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param game
|
||||
* @param source
|
||||
* @return
|
||||
|
|
@ -883,7 +880,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
if (!this.hasSourceObjectAbility(game, source, event)) {
|
||||
return false;
|
||||
}
|
||||
if (zone.equals(Zone.COMMAND)) {
|
||||
if (zone == Zone.COMMAND) {
|
||||
if (this.getSourceId() == null) { // commander effects
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1027,7 +1024,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
sb.append("unknown");
|
||||
}
|
||||
if (object instanceof Spell && ((Spell) object).getSpellAbilities().size() > 1) {
|
||||
if (((Spell) object).getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) {
|
||||
if (((Spell) object).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
|
||||
Spell spell = (Spell) object;
|
||||
int i = 0;
|
||||
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ package mage.abilities.common;
|
|||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.EntersBattlefieldEffect;
|
||||
import mage.constants.EnterEventType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
|
|
@ -39,14 +40,18 @@ import mage.constants.Zone;
|
|||
public class AsEntersBattlefieldAbility extends StaticAbility {
|
||||
|
||||
public AsEntersBattlefieldAbility(Effect effect) {
|
||||
super(Zone.ALL, new EntersBattlefieldEffect(effect));
|
||||
this(effect, null, EnterEventType.OTHER);
|
||||
}
|
||||
|
||||
public AsEntersBattlefieldAbility(Effect effect, String text) {
|
||||
super(Zone.ALL, new EntersBattlefieldEffect(effect, text));
|
||||
this(effect, text, EnterEventType.OTHER);
|
||||
}
|
||||
|
||||
public AsEntersBattlefieldAbility(AsEntersBattlefieldAbility ability) {
|
||||
public AsEntersBattlefieldAbility(Effect effect, String text, EnterEventType enterEventType) {
|
||||
super(Zone.ALL, new EntersBattlefieldEffect(effect, null, text, true, false, enterEventType));
|
||||
}
|
||||
|
||||
public AsEntersBattlefieldAbility(final AsEntersBattlefieldAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import mage.game.permanent.Permanent;
|
|||
import mage.game.permanent.PermanentToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class DiesTriggeredAbility extends ZoneChangeTriggeredAbility {
|
||||
|
|
@ -69,7 +68,7 @@ public class DiesTriggeredAbility extends ZoneChangeTriggeredAbility {
|
|||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
if (super.checkEventType(event, game)) {
|
||||
return ((ZoneChangeEvent) event).getFromZone().equals(Zone.BATTLEFIELD) && ((ZoneChangeEvent) event).getToZone().equals(Zone.GRAVEYARD);
|
||||
return ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
protected FilterPermanent filter;
|
||||
protected String rule;
|
||||
protected boolean controlled;
|
||||
protected boolean controlledText;
|
||||
protected SetTargetPointer setTargetPointer;
|
||||
|
||||
/**
|
||||
|
|
@ -71,19 +71,19 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
|
|||
this(zone, effect, filter, optional, rule, false);
|
||||
}
|
||||
|
||||
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule, boolean controlled) {
|
||||
this(zone, effect, filter, optional, SetTargetPointer.NONE, rule, controlled);
|
||||
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule, boolean controlledText) {
|
||||
this(zone, effect, filter, optional, SetTargetPointer.NONE, rule, controlledText);
|
||||
}
|
||||
|
||||
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule) {
|
||||
this(zone, effect, filter, optional, setTargetPointer, rule, false);
|
||||
}
|
||||
|
||||
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule, boolean controlled) {
|
||||
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule, boolean controlledText) {
|
||||
super(zone, effect, optional);
|
||||
this.filter = filter;
|
||||
this.rule = rule;
|
||||
this.controlled = controlled;
|
||||
this.controlledText = controlledText;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
|
|||
super(ability);
|
||||
this.filter = ability.filter;
|
||||
this.rule = ability.rule;
|
||||
this.controlled = ability.controlled;
|
||||
this.controlledText = ability.controlledText;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
StringBuilder sb = new StringBuilder("Whenever ").append(filter.getMessage());
|
||||
sb.append(" enters the battlefield");
|
||||
if (controlled) {
|
||||
if (controlledText) {
|
||||
sb.append(" under your control, ");
|
||||
} else {
|
||||
sb.append(", ");
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import mage.game.events.GameEvent.EventType;
|
|||
import mage.game.events.ZoneChangeEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EntersBattlefieldOrLeavesSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
|
@ -68,7 +67,7 @@ public class EntersBattlefieldOrLeavesSourceTriggeredAbility extends TriggeredAb
|
|||
}
|
||||
if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (zEvent.getFromZone().equals(Zone.BATTLEFIELD)) {
|
||||
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +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 = (StackObject) game.getStack().getStackObject(event.getSourceId());
|
||||
if (stackObjectThatCountered == null) {
|
||||
stackObjectThatCountered = (StackObject) game.getLastKnownInformation(event.getSourceId(), Zone.STACK);
|
||||
}
|
||||
if (stackObjectThatCountered != null && stackObjectThatCountered.getControllerId().equals(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();
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ 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;
|
||||
|
||||
|
|
@ -39,7 +40,6 @@ import mage.game.permanent.Permanent;
|
|||
*
|
||||
* @author emerald000
|
||||
*/
|
||||
|
||||
public class MeldCondition implements Condition {
|
||||
|
||||
private final String meldWithName;
|
||||
|
|
@ -57,11 +57,8 @@ public class MeldCondition implements Condition {
|
|||
&& sourcePermanent.getOwnerId().equals(source.getControllerId())) {
|
||||
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
|
||||
filter.add(new NamePredicate(this.meldWithName));
|
||||
for (Permanent meldWithPermanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (meldWithPermanent.getOwnerId().equals(source.getControllerId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
filter.add(new OwnerIdPredicate(source.getControllerId()));
|
||||
return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import mage.constants.AbilityType;
|
|||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ public class ConditionalManaEffect extends ManaEffect {
|
|||
}
|
||||
|
||||
if (mana != null) {
|
||||
checkToFirePossibleEvents(mana, game, source);
|
||||
controller.getManaPool().addMana(mana, game, source);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -114,9 +115,6 @@ public class ConditionalManaEffect extends ManaEffect {
|
|||
} else if (otherwiseEffect != null) {
|
||||
mana = otherwiseEffect.getMana();
|
||||
}
|
||||
if (mana != null) {
|
||||
checkToFirePossibleEvents(mana, game, source);
|
||||
}
|
||||
return mana;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.EnterEventType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
|
@ -50,6 +51,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
protected String text;
|
||||
protected Condition condition;
|
||||
protected boolean optional;
|
||||
protected EnterEventType enterEventType;
|
||||
|
||||
public static final String SOURCE_CAST_SPELL_ABILITY = "sourceCastSpellAbility";
|
||||
|
||||
|
|
@ -66,19 +68,25 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
|
||||
public EntersBattlefieldEffect(Effect baseEffect, Condition condition, String text, boolean selfScope, boolean optional) {
|
||||
this(baseEffect, condition, text, selfScope, optional, EnterEventType.OTHER);
|
||||
}
|
||||
|
||||
public EntersBattlefieldEffect(Effect baseEffect, Condition condition, String text, boolean selfScope, boolean optional, EnterEventType enterEventType) {
|
||||
super(Duration.WhileOnBattlefield, baseEffect.getOutcome(), selfScope);
|
||||
this.baseEffects.add(baseEffect);
|
||||
this.enterEventType = enterEventType;
|
||||
this.text = text;
|
||||
this.condition = condition;
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
public EntersBattlefieldEffect(EntersBattlefieldEffect effect) {
|
||||
public EntersBattlefieldEffect(final EntersBattlefieldEffect effect) {
|
||||
super(effect);
|
||||
this.baseEffects = effect.baseEffects.copy();
|
||||
this.text = effect.text;
|
||||
this.condition = effect.condition;
|
||||
this.optional = effect.optional;
|
||||
this.enterEventType = effect.enterEventType;
|
||||
}
|
||||
|
||||
public void addEffect(Effect effect) {
|
||||
|
|
@ -87,7 +95,17 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return EventType.ENTERS_THE_BATTLEFIELD.equals(event.getType());
|
||||
switch (enterEventType) {
|
||||
case OTHER:
|
||||
return EventType.ENTERS_THE_BATTLEFIELD.equals(event.getType());
|
||||
case SELF:
|
||||
return EventType.ENTERS_THE_BATTLEFIELD_SELF.equals(event.getType());
|
||||
case CONTROL:
|
||||
return EventType.ENTERS_THE_BATTLEFIELD_CONTROL.equals(event.getType());
|
||||
case COPY:
|
||||
return EventType.ENTERS_THE_BATTLEFIELD_COPY.equals(event.getType());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.choices.ChoiceColor;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* Created by Galatolol
|
||||
*/
|
||||
public class AddManaOfAnyColorToManaPoolTargetPlayerEffect extends ManaEffect {
|
||||
|
||||
public AddManaOfAnyColorToManaPoolTargetPlayerEffect(String textManaPoolOwner) {
|
||||
super();
|
||||
this.staticText = (textManaPoolOwner.equals("his or her")?"that player adds ":"add ") + "one mana of any color" + " to " + textManaPoolOwner + " mana pool";
|
||||
}
|
||||
|
||||
public AddManaOfAnyColorToManaPoolTargetPlayerEffect(final AddManaOfAnyColorToManaPoolTargetPlayerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID playerId = (UUID) game.getState().getValue(source.getSourceId() + "_player");
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
ChoiceColor choice = new ChoiceColor();
|
||||
while (!player.choose(outcome, choice, game)) {
|
||||
if (!player.canRespond()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Mana mana = choice.getMana(1);
|
||||
if (mana != null) {
|
||||
checkToFirePossibleEvents(mana, game, source);
|
||||
player.getManaPool().addMana(mana, game, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddManaOfAnyColorToManaPoolTargetPlayerEffect copy() {
|
||||
return new AddManaOfAnyColorToManaPoolTargetPlayerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana getMana(Game game, Ability source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -96,12 +96,16 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect {
|
|||
switch (zoneDetail) {
|
||||
case BOTTOM:
|
||||
sb.append("the bottom");
|
||||
break;
|
||||
case TOP:
|
||||
sb.append("top");
|
||||
break;
|
||||
case CHOOSE:
|
||||
sb.append("top or bottom");
|
||||
break;
|
||||
case NONE:
|
||||
sb.append("<not allowed value>");
|
||||
break;
|
||||
}
|
||||
sb.append(" of its owner's library instead of into that player's graveyard");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,8 +137,8 @@ public class ExileTargetEffect extends OneShotEffect {
|
|||
}
|
||||
} else {
|
||||
StackObject stackObject = game.getStack().getStackObject(targetId);
|
||||
if (stackObject instanceof Spell && ((Spell) stackObject).getCard() != null) {
|
||||
toExile.add(((Spell) stackObject).getCard());
|
||||
if (stackObject instanceof Spell) {
|
||||
toExile.add((Spell) stackObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public abstract class ManaEffect extends OneShotEffect {
|
|||
* @param source
|
||||
*/
|
||||
public void checkToFirePossibleEvents(Mana mana, Game game, Ability source) {
|
||||
if (source.getAbilityType().equals(AbilityType.MANA)) {
|
||||
if (source.getAbilityType()==AbilityType.MANA) {
|
||||
for (Cost cost: source.getCosts()) {
|
||||
if (cost instanceof TapSourceCost) {
|
||||
ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, source.getSourceId(), source.getSourceId(), source.getControllerId(), mana);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -93,12 +94,14 @@ public class MeldEffect extends OneShotEffect {
|
|||
Permanent sourcePermanent = game.getPermanent(sourceId);
|
||||
Permanent meldWithPermanent = game.getPermanent(meldWithId);
|
||||
if (sourcePermanent != null && meldWithPermanent != null) {
|
||||
sourcePermanent.moveToExile(null, "", sourceId, game);
|
||||
meldWithPermanent.moveToExile(null, "", sourceId, game);
|
||||
Set<Card> toExile = new HashSet<>();
|
||||
toExile.add(sourcePermanent);
|
||||
toExile.add(meldWithPermanent);
|
||||
controller.moveCards(toExile, Zone.EXILED, source, game);
|
||||
// Create the meld card and move it to the battlefield.
|
||||
Card sourceCard = game.getExile().getCard(sourceId, game);
|
||||
Card meldWithCard = game.getExile().getCard(meldWithId, game);
|
||||
if (!sourceCard.isCopy() && !meldWithCard.isCopy()) {
|
||||
if (sourceCard != null && !sourceCard.isCopy() && meldWithCard != null && !meldWithCard.isCopy()) {
|
||||
meldCard.setOwnerId(controller.getId());
|
||||
meldCard.setTopHalfCard(meldWithCard, game);
|
||||
meldCard.setBottomHalfCard(sourceCard, game);
|
||||
|
|
@ -106,7 +109,7 @@ public class MeldEffect extends OneShotEffect {
|
|||
game.addMeldCard(meldCard.getId(), meldCard);
|
||||
game.getState().addCard(meldCard);
|
||||
meldCard.setZone(Zone.EXILED, game);
|
||||
meldCard.moveToZone(Zone.BATTLEFIELD, sourceId, game, false);
|
||||
controller.moveCards(meldCard, Zone.BATTLEFIELD, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class PreventDamageToControllerEffect extends PreventionEffectImpl {
|
|||
sb.append("combat ");
|
||||
}
|
||||
sb.append("damage that would be dealt to you");
|
||||
if (duration.equals(Duration.EndOfTurn)) {
|
||||
if (duration == Duration.EndOfTurn) {
|
||||
sb.append(" this turn");
|
||||
}
|
||||
return sb.toString();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -42,7 +41,7 @@ public class SwordsToPlowsharesEffect extends OneShotEffect {
|
|||
|
||||
public SwordsToPlowsharesEffect() {
|
||||
super(Outcome.GainLife);
|
||||
staticText = "Its controller gains life equal to its power";
|
||||
staticText = "Exile target creature. Its controller gains life equal to its power";
|
||||
}
|
||||
|
||||
public SwordsToPlowsharesEffect(final SwordsToPlowsharesEffect effect) {
|
||||
|
|
@ -60,7 +59,9 @@ public class SwordsToPlowsharesEffect extends OneShotEffect {
|
|||
if (permanent != null) {
|
||||
Player player = game.getPlayer(permanent.getControllerId());
|
||||
if (player != null) {
|
||||
player.gainLife(permanent.getPower().getValue(), game);
|
||||
int creaturePower = permanent.getPower().getValue();
|
||||
permanent.moveToExile(null, null, source.getSourceId(), game);
|
||||
player.gainLife(creaturePower, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,9 +91,8 @@ public class DiscardTargetEffect extends OneShotEffect {
|
|||
if (player != null) {
|
||||
player.discard(amount.calculate(game, source, this), randomDiscard, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects.common.enterAttribute;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect {
|
||||
|
||||
public EnterAttributeAddChosenSubtypeEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "{this} is the chosen type in addition to its other types";
|
||||
}
|
||||
|
||||
public EnterAttributeAddChosenSubtypeEffect(final EnterAttributeAddChosenSubtypeEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnterAttributeAddChosenSubtypeEffect copy() {
|
||||
return new EnterAttributeAddChosenSubtypeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
String subtype = (String) game.getState().getValue(source.getSourceId() + "_type");
|
||||
if (permanent != null && subtype != null) {
|
||||
MageObject mageObject = permanent.getBasicMageObject(game);
|
||||
if (!mageObject.getSubtype(null).contains(subtype)) {
|
||||
mageObject.getSubtype(null).add(subtype);
|
||||
}
|
||||
if (!permanent.getSubtype(null).contains(subtype)) {
|
||||
permanent.getSubtype(null).add(subtype);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects.common.search;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class SearchLibraryGraveyardPutInHandEffect extends OneShotEffect {
|
||||
|
||||
private FilterCard filter;
|
||||
private boolean forceToSearchBoth;
|
||||
|
||||
public SearchLibraryGraveyardPutInHandEffect(FilterCard filter) {
|
||||
this(filter, false);
|
||||
}
|
||||
|
||||
public SearchLibraryGraveyardPutInHandEffect(FilterCard filter, boolean forceToSearchBoth) {
|
||||
super(Outcome.Benefit);
|
||||
this.filter = filter;
|
||||
this.forceToSearchBoth = forceToSearchBoth;
|
||||
staticText = "Search your library and" + (forceToSearchBoth ? "" : "/or ") + " graveyard for a card named " + filter.getMessage() + ", reveal it, and put it into your hand. Then shuffle your library";
|
||||
}
|
||||
|
||||
public SearchLibraryGraveyardPutInHandEffect(final SearchLibraryGraveyardPutInHandEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
this.forceToSearchBoth = effect.forceToSearchBoth;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchLibraryGraveyardPutInHandEffect copy() {
|
||||
return new SearchLibraryGraveyardPutInHandEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
Card cardFound = null;
|
||||
if (controller != null && sourceObject != null) {
|
||||
if (forceToSearchBoth || controller.chooseUse(outcome, "Search your library for a card named " + filter.getMessage() + "?", source, game)) {
|
||||
TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter);
|
||||
target.clearChosen();
|
||||
if (controller.searchLibrary(target, game)) {
|
||||
if (target.getTargets().size() > 0) {
|
||||
cardFound = game.getCard(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
controller.shuffleLibrary(source, game);
|
||||
}
|
||||
|
||||
if (cardFound == null && controller.chooseUse(outcome, "Search your graveyard for a card named " + filter.getMessage() + "?", source, game)) {
|
||||
TargetCard target = new TargetCard(0, 1, Zone.GRAVEYARD, filter);
|
||||
target.clearChosen();
|
||||
if (controller.choose(outcome, controller.getGraveyard(), target, game)) {
|
||||
if (target.getTargets().size() > 0) {
|
||||
cardFound = game.getCard(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cardFound != null) {
|
||||
controller.revealCards(sourceObject.getIdName(), new CardsImpl(cardFound), game);
|
||||
controller.moveCards(cardFound, Zone.HAND, source, game);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.abilities.effects.common.search;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class SearchLibraryWithLessCMCPutInPlayEffect extends OneShotEffect {
|
||||
|
||||
private FilterCard filter;
|
||||
|
||||
public SearchLibraryWithLessCMCPutInPlayEffect() {
|
||||
this(new FilterCard());
|
||||
}
|
||||
|
||||
public SearchLibraryWithLessCMCPutInPlayEffect(FilterCard filter) {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
this.filter = filter;
|
||||
staticText = "Search your library for a " + filter.getMessage() + " with converted mana cost X or less, put it onto the battlefield, then shuffle your library";
|
||||
}
|
||||
|
||||
public SearchLibraryWithLessCMCPutInPlayEffect(final SearchLibraryWithLessCMCPutInPlayEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, source.getManaCostsToPay().getX() + 1));
|
||||
TargetCardInLibrary target = new TargetCardInLibrary(filter);
|
||||
if (controller.searchLibrary(target, game)) {
|
||||
if (target.getTargets().size() > 0) {
|
||||
Card card = controller.getLibrary().getCard(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
}
|
||||
}
|
||||
controller.shuffleLibrary(source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchLibraryWithLessCMCPutInPlayEffect copy() {
|
||||
return new SearchLibraryWithLessCMCPutInPlayEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,25 +27,23 @@
|
|||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.continuous.SourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.DependencyType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
|
@ -123,7 +121,7 @@ public class BestowAbility extends SpellAbility {
|
|||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.addTarget(auraTarget);
|
||||
this.addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BestowTypeChangingEffect());
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BestowEntersBattlefieldEffect());
|
||||
ability.setRuleVisible(false);
|
||||
addSubAbility(ability);
|
||||
}
|
||||
|
|
@ -147,64 +145,60 @@ public class BestowAbility extends SpellAbility {
|
|||
return "Bestow " + getManaCostsToPay().getText() + " <i>(If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)</i>";
|
||||
}
|
||||
|
||||
class BestowTypeChangingEffect extends ContinuousEffectImpl implements SourceEffect {
|
||||
|
||||
private boolean wasAttached;
|
||||
|
||||
public BestowTypeChangingEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.BoostCreature);
|
||||
wasAttached = false;
|
||||
dependencyTypes.add(DependencyType.AuraAddingRemoving);
|
||||
}
|
||||
|
||||
public BestowTypeChangingEffect(final BestowTypeChangingEffect effect) {
|
||||
super(effect);
|
||||
this.wasAttached = effect.wasAttached;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BestowTypeChangingEffect copy() {
|
||||
return new BestowTypeChangingEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (permanent.getAttachedTo() == null) {
|
||||
if (wasAttached && permanent.getSubtype(game).contains("Aura")) {
|
||||
permanent.getSubtype(game).remove("Aura");
|
||||
wasAttached = false;
|
||||
}
|
||||
} else {
|
||||
permanent.getCardType().remove(CardType.CREATURE);
|
||||
permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes());
|
||||
if (!permanent.getSubtype(game).contains("Aura")) {
|
||||
permanent.getSubtype(game).add("Aura");
|
||||
}
|
||||
wasAttached = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
static public void becomeCreature(Permanent permanent, Game game) {
|
||||
if (permanent != null) {
|
||||
MageObject basicObject = permanent.getBasicMageObject(game);
|
||||
if (basicObject != null) {
|
||||
basicObject.getSubtype(null).remove("Aura");
|
||||
if (!basicObject.getCardType().contains(CardType.CREATURE)) {
|
||||
basicObject.getCardType().add(CardType.CREATURE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
permanent.getSubtype(null).remove("Aura");
|
||||
if (!permanent.getCardType().contains(CardType.CREATURE)) {
|
||||
permanent.getCardType().add(CardType.CREATURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.TypeChangingEffects_4;
|
||||
class BestowEntersBattlefieldEffect extends ReplacementEffectImpl {
|
||||
|
||||
public BestowEntersBattlefieldEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
||||
}
|
||||
|
||||
public BestowEntersBattlefieldEffect(final BestowEntersBattlefieldEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return EventType.ENTERS_THE_BATTLEFIELD_SELF.equals(event.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return event.getTargetId().equals(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Permanent bestowPermanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (bestowPermanent != null) {
|
||||
if (bestowPermanent.getSubtype(game).contains("Aura")) {
|
||||
MageObject basicObject = bestowPermanent.getBasicMageObject(game);
|
||||
basicObject.getSubtype(null).add("Aura");
|
||||
basicObject.getCardType().remove(CardType.CREATURE);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BestowEntersBattlefieldEffect copy() {
|
||||
return new BestowEntersBattlefieldEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpecialAction;
|
||||
|
|
@ -30,7 +31,6 @@ import mage.target.Target;
|
|||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ImproviseAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
|
||||
|
|
@ -59,7 +59,7 @@ public class ImproviseAbility extends SimpleStaticAbility implements AlternateMa
|
|||
public void addSpecialAction(Ability source, Game game, ManaCost unpaid) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null && game.getBattlefield().contains(filterUntapped, controller.getId(), 1, game)) {
|
||||
if (source.getAbilityType().equals(AbilityType.SPELL) && unpaid.getMana().getGeneric() > 0) {
|
||||
if (source.getAbilityType() == AbilityType.SPELL && unpaid.getMana().getGeneric() > 0) {
|
||||
SpecialAction specialAction = new ImproviseSpecialAction(unpaid);
|
||||
specialAction.setControllerId(source.getControllerId());
|
||||
specialAction.setSourceId(source.getSourceId());
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ package mage.abilities.keyword;
|
|||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import mage.constants.Zone;
|
|||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.*;
|
||||
import mage.game.command.Commander;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
|
|||
|
|
@ -230,9 +230,7 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
|
|||
Map<String, Card> cards = new HashMap<>();
|
||||
for (UUID cardId : this) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (!cards.containsKey(card.getName())) {
|
||||
cards.put(card.getName(), card);
|
||||
}
|
||||
cards.putIfAbsent(card.getName(), card);
|
||||
}
|
||||
return cards.values();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ public abstract class ExpansionSet implements Serializable {
|
|||
Iterator<CardInfo> iterator = savedCardsInfos.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CardInfo next = iterator.next();
|
||||
if (Integer.valueOf(next.getCardNumber()) > maxCardNumberInBooster) {
|
||||
if (Integer.valueOf(next.getCardNumber()) > maxCardNumberInBooster && !rarity.equals(Rarity.LAND)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@ public abstract class MeldCard extends CardImpl {
|
|||
halves = new CardsImpl();
|
||||
}
|
||||
|
||||
public MeldCard(MeldCard card) {
|
||||
public MeldCard(final MeldCard card) {
|
||||
super(card);
|
||||
this.topHalfCard = card.topHalfCard;
|
||||
this.bottomHalfCard = card.bottomHalfCard;
|
||||
this.topLastZoneChangeCounter = card.topLastZoneChangeCounter;
|
||||
this.bottomLastZoneChangeCounter = card.bottomLastZoneChangeCounter;
|
||||
this.halves = new CardsImpl(halves);
|
||||
this.halves = new CardsImpl(card.halves);
|
||||
this.isMelded = card.isMelded;
|
||||
}
|
||||
|
||||
|
|
@ -211,4 +211,5 @@ public abstract class MeldCard extends CardImpl {
|
|||
public Cards getHalves() {
|
||||
return halves;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public enum CardRepository {
|
|||
// raise this if db structure was changed
|
||||
private static final long CARD_DB_VERSION = 50;
|
||||
// raise this if new cards were added to the server
|
||||
private static final long CARD_CONTENT_VERSION = 67;
|
||||
private static final long CARD_CONTENT_VERSION = 68;
|
||||
private final TreeSet<String> landTypes = new TreeSet();
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
private Set<String> classNames;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class ExpansionInfo {
|
|||
|
||||
@DatabaseField(unique = true)
|
||||
protected String name;
|
||||
@DatabaseField(unique = true)
|
||||
@DatabaseField(id = true,unique = true)
|
||||
protected String code;
|
||||
@DatabaseField
|
||||
protected String blockName;
|
||||
|
|
|
|||
12
Mage/src/main/java/mage/constants/EnterEventType.java
Normal file
12
Mage/src/main/java/mage/constants/EnterEventType.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package mage.constants;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public enum EnterEventType {
|
||||
SELF,
|
||||
CONTROL,
|
||||
COPY,
|
||||
OTHER
|
||||
}
|
||||
|
|
@ -47,4 +47,7 @@ public enum Zone {
|
|||
return super.toString();
|
||||
}
|
||||
|
||||
public static boolean isPublicZone(Zone zone) {
|
||||
return GRAVEYARD.equals(zone) || BATTLEFIELD.equals(zone) || STACK.equals(zone) || EXILED.equals(zone) || COMMAND.equals(zone);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,13 +73,6 @@ public class Counter implements Serializable {
|
|||
this.count = counter.count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the {@code count} by 1
|
||||
*/
|
||||
public void increase() {
|
||||
count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the passed in {@code amount} to the {@code count}
|
||||
*
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.counters;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -35,15 +34,15 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class Counters extends HashMap<String, Counter> implements Serializable {
|
||||
|
||||
public Counters() {}
|
||||
public Counters() {
|
||||
}
|
||||
|
||||
public Counters(final Counters counters) {
|
||||
for (Map.Entry<String, Counter> entry: counters.entrySet()) {
|
||||
for (Map.Entry<String, Counter> entry : counters.entrySet()) {
|
||||
this.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
}
|
||||
|
|
@ -52,17 +51,8 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
|
|||
return new Counters(this);
|
||||
}
|
||||
|
||||
public void addCounter(String name) {
|
||||
if (!this.containsKey(name)) {
|
||||
this.put(name, new Counter(name));
|
||||
}
|
||||
this.get(name).increase();
|
||||
}
|
||||
|
||||
public void addCounter(String name, int amount) {
|
||||
if (!this.containsKey(name)) {
|
||||
this.put(name, new Counter(name));
|
||||
}
|
||||
putIfAbsent(name, new Counter(name));
|
||||
this.get(name).add(amount);
|
||||
}
|
||||
|
||||
|
|
@ -100,13 +90,14 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void removeAllCounters(CounterType counterType){
|
||||
public void removeAllCounters(CounterType counterType) {
|
||||
removeAllCounters(counterType.getName());
|
||||
}
|
||||
|
||||
public void removeAllCounters(String name){
|
||||
if (this.containsKey(name)){
|
||||
public void removeAllCounters(String name) {
|
||||
if (this.containsKey(name)) {
|
||||
this.remove(name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,9 +121,9 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
|
|||
|
||||
public List<BoostCounter> getBoostCounters() {
|
||||
List<BoostCounter> boosters = new ArrayList<>();
|
||||
for (Counter counter: this.values()) {
|
||||
for (Counter counter : this.values()) {
|
||||
if (counter instanceof BoostCounter) {
|
||||
boosters.add((BoostCounter)counter);
|
||||
boosters.add((BoostCounter) counter);
|
||||
}
|
||||
}
|
||||
return boosters;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.game;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -38,7 +37,6 @@ import mage.abilities.effects.common.InfoEffect;
|
|||
import mage.abilities.effects.common.continuous.CommanderReplacementEffect;
|
||||
import mage.abilities.effects.common.cost.CommanderCostModification;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
|
|
@ -49,11 +47,8 @@ import mage.watchers.common.CommanderInfoWatcher;
|
|||
|
||||
public abstract class GameCommanderImpl extends GameImpl {
|
||||
|
||||
static boolean CHECK_COMMANDER_DAMAGE = true;
|
||||
|
||||
private final Map<UUID, Cards> mulliganedCards = new HashMap<>();
|
||||
// private final Set<CommanderInfoWatcher> commanderCombatWatcher = new HashSet<>();
|
||||
|
||||
// private final Map<UUID, Cards> mulliganedCards = new HashMap<>();
|
||||
protected boolean checkCommanderDamage = true;
|
||||
protected boolean alsoHand; // replace commander going to hand
|
||||
protected boolean alsoLibrary; // replace commander going to library
|
||||
protected boolean startingPlayerSkipsDraw = true;
|
||||
|
|
@ -67,6 +62,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
this.alsoHand = game.alsoHand;
|
||||
this.alsoLibrary = game.alsoLibrary;
|
||||
this.startingPlayerSkipsDraw = game.startingPlayerSkipsDraw;
|
||||
this.checkCommanderDamage = game.checkCommanderDamage;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -85,7 +81,7 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
|
||||
ability.addEffect(new CommanderCostModification(commander.getId()));
|
||||
getState().setValue(commander.getId() + "_castCount", 0);
|
||||
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), CHECK_COMMANDER_DAMAGE);
|
||||
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), checkCommanderDamage);
|
||||
getState().getWatchers().add(watcher);
|
||||
watcher.addCardInfoToCommander(this);
|
||||
}
|
||||
|
|
@ -227,4 +223,13 @@ public abstract class GameCommanderImpl extends GameImpl {
|
|||
public void setAlsoLibrary(boolean alsoLibrary) {
|
||||
this.alsoLibrary = alsoLibrary;
|
||||
}
|
||||
|
||||
public boolean isCheckCommanderDamage() {
|
||||
return checkCommanderDamage;
|
||||
}
|
||||
|
||||
public void setCheckCommanderDamage(boolean checkCommanderDamage) {
|
||||
this.checkCommanderDamage = checkCommanderDamage;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import mage.abilities.effects.ContinuousEffects;
|
|||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.common.CopyEffect;
|
||||
import mage.abilities.keyword.BestowAbility;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.abilities.mana.DelayedTriggeredManaAbility;
|
||||
|
|
@ -109,7 +110,6 @@ import mage.game.events.TableEventSource;
|
|||
import mage.game.permanent.Battlefield;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.permanent.PermanentImpl;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.SpellStack;
|
||||
import mage.game.stack.StackObject;
|
||||
|
|
@ -1788,7 +1788,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
} else {
|
||||
SpellAbility spellAbility = perm.getSpellAbility();
|
||||
if (perm.getSpellAbility().getTargets().isEmpty()) {
|
||||
if (spellAbility.getTargets().isEmpty()) {
|
||||
for (Ability ability : perm.getAbilities(this)) {
|
||||
if ((ability instanceof SpellAbility)
|
||||
&& SpellAbilityType.BASE_ALTERNATE.equals(((SpellAbility) ability).getSpellAbilityType())
|
||||
|
|
@ -1811,6 +1811,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (card != null && card.getCardType().contains(CardType.CREATURE)) {
|
||||
UUID wasAttachedTo = perm.getAttachedTo();
|
||||
perm.attachTo(null, this);
|
||||
BestowAbility.becomeCreature(perm, this);
|
||||
fireEvent(new GameEvent(GameEvent.EventType.UNATTACHED, wasAttachedTo, perm.getId(), perm.getControllerId()));
|
||||
} else if (movePermanentToGraveyardWithInfo(perm)) {
|
||||
somethingHappened = true;
|
||||
|
|
@ -2676,17 +2677,17 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
card.setZone(Zone.GRAVEYARD, this);
|
||||
player.getGraveyard().add(card);
|
||||
}
|
||||
for (PermanentCard card : battlefield) {
|
||||
card.setZone(Zone.BATTLEFIELD, this);
|
||||
card.setOwnerId(ownerId);
|
||||
PermanentCard permanent = new PermanentCard(card.getCard(), ownerId, this);
|
||||
getPermanentsEntering().put(permanent.getId(), permanent);
|
||||
permanent.entersBattlefield(permanent.getId(), this, Zone.OUTSIDE, false);
|
||||
getBattlefield().addPermanent(permanent);
|
||||
getPermanentsEntering().remove(permanent.getId());
|
||||
permanent.removeSummoningSickness();
|
||||
if (card.isTapped()) {
|
||||
permanent.setTapped(true);
|
||||
for (PermanentCard permanentCard : battlefield) {
|
||||
permanentCard.setZone(Zone.BATTLEFIELD, this);
|
||||
permanentCard.setOwnerId(ownerId);
|
||||
PermanentCard newPermanent = new PermanentCard(permanentCard.getCard(), ownerId, this);
|
||||
getPermanentsEntering().put(newPermanent.getId(), newPermanent);
|
||||
newPermanent.entersBattlefield(newPermanent.getId(), this, Zone.OUTSIDE, false);
|
||||
getBattlefield().addPermanent(newPermanent);
|
||||
getPermanentsEntering().remove(newPermanent.getId());
|
||||
newPermanent.removeSummoningSickness();
|
||||
if (permanentCard.isTapped()) {
|
||||
newPermanent.setTapped(true);
|
||||
}
|
||||
}
|
||||
applyEffects();
|
||||
|
|
|
|||
|
|
@ -64,9 +64,7 @@ public class LookedAt extends HashMap<String, Cards> implements Serializable, Co
|
|||
}
|
||||
|
||||
public Cards createLookedAt(String name) {
|
||||
if (!this.containsKey(name)) {
|
||||
this.put(name, new CardsImpl());
|
||||
}
|
||||
putIfAbsent(name, new CardsImpl());
|
||||
return this.get(name);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,8 +204,7 @@ public class ZonesHandler {
|
|||
// If we can't find the card we can't remove it.
|
||||
return false;
|
||||
}
|
||||
// If needed take attributes from the spell (e.g. color of spell was changed)
|
||||
card = takeAttributesFromSpell(card, event, game);
|
||||
|
||||
boolean success = false;
|
||||
if (info.faceDown) {
|
||||
card.setFaceDown(true, game);
|
||||
|
|
@ -213,6 +212,8 @@ public class ZonesHandler {
|
|||
if (!game.replaceEvent(event)) {
|
||||
Zone fromZone = event.getFromZone();
|
||||
if (event.getToZone() == Zone.BATTLEFIELD) {
|
||||
// If needed take attributes from the spell (e.g. color of spell was changed)
|
||||
card = takeAttributesFromSpell(card, event, game);
|
||||
// controlling player can be replaced so use event player now
|
||||
Permanent permanent;
|
||||
if (card instanceof MeldCard) {
|
||||
|
|
@ -232,7 +233,6 @@ public class ZonesHandler {
|
|||
if (info.faceDown) {
|
||||
card.setFaceDown(false, game);
|
||||
}
|
||||
|
||||
// make sure the controller of all continuous effects of this card are switched to the current controller
|
||||
game.setScopeRelevant(true);
|
||||
game.getContinuousEffects().setController(permanent.getId(), permanent.getControllerId());
|
||||
|
|
@ -282,16 +282,12 @@ public class ZonesHandler {
|
|||
}
|
||||
|
||||
private static Card takeAttributesFromSpell(Card card, ZoneChangeEvent event, Game game) {
|
||||
card = card.copy();
|
||||
if (Zone.STACK.equals(event.getFromZone())) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell != null && !spell.isFaceDown(game)) {
|
||||
boolean doCopy = false;
|
||||
if (!card.getColor(game).equals(spell.getColor(game))) {
|
||||
doCopy = true;
|
||||
}
|
||||
if (doCopy) {
|
||||
// the card that is referenced to in the permanent is copied and the spell attributes are set to this copied card
|
||||
card = card.copy();
|
||||
card.getColor(game).setColor(spell.getColor(game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.constants.EnterEventType;
|
||||
import static mage.constants.EnterEventType.SELF;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
|
@ -43,17 +43,24 @@ public class EntersTheBattlefieldEvent extends GameEvent {
|
|||
private Permanent target;
|
||||
|
||||
public EntersTheBattlefieldEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone) {
|
||||
super(EventType.ENTERS_THE_BATTLEFIELD, target.getId(), sourceId, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.target = target;
|
||||
this(target, sourceId, playerId, fromZone, EnterEventType.OTHER);
|
||||
}
|
||||
|
||||
public EntersTheBattlefieldEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, ArrayList<UUID> appliedEffects) {
|
||||
public EntersTheBattlefieldEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, EnterEventType enterType) {
|
||||
super(EventType.ENTERS_THE_BATTLEFIELD, target.getId(), sourceId, playerId);
|
||||
this.fromZone = fromZone;
|
||||
if (appliedEffects != null) {
|
||||
this.appliedEffects = appliedEffects;
|
||||
switch (enterType) {
|
||||
case SELF:
|
||||
type = EventType.ENTERS_THE_BATTLEFIELD_SELF;
|
||||
break;
|
||||
case CONTROL:
|
||||
type = EventType.ENTERS_THE_BATTLEFIELD_CONTROL;
|
||||
break;
|
||||
case COPY:
|
||||
type = EventType.ENTERS_THE_BATTLEFIELD_COPY;
|
||||
break;
|
||||
}
|
||||
this.fromZone = fromZone;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public Zone getFromZone() {
|
||||
|
|
|
|||
|
|
@ -229,7 +229,10 @@ public class GameEvent implements Serializable {
|
|||
PAID_CUMULATIVE_UPKEEP,
|
||||
DIDNT_PAY_CUMULATIVE_UPKEEP,
|
||||
//permanent events
|
||||
ENTERS_THE_BATTLEFIELD,
|
||||
ENTERS_THE_BATTLEFIELD_SELF, // 616.1a If any of the replacement and/or prevention effects are self-replacement effects (see rule 614.15), one of them must be chosen. If not, proceed to rule 616.1b.
|
||||
ENTERS_THE_BATTLEFIELD_CONTROL, // 616.1b
|
||||
ENTERS_THE_BATTLEFIELD_COPY, // 616.1c
|
||||
ENTERS_THE_BATTLEFIELD, // 616.1d
|
||||
TAP, TAPPED, TAPPED_FOR_MANA,
|
||||
UNTAP, UNTAPPED,
|
||||
FLIP, FLIPPED,
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
void reset(Game game);
|
||||
|
||||
MageObject getBasicMageObject(Game game);
|
||||
|
||||
boolean destroy(UUID sourceId, Game game, boolean noRegen);
|
||||
|
||||
boolean sacrifice(UUID sourceId, Game game);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
package mage.game.permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
|
|
@ -44,6 +45,7 @@ import mage.game.events.ZoneChangeEvent;
|
|||
public class PermanentCard extends PermanentImpl {
|
||||
|
||||
protected int maxLevelCounters;
|
||||
// A copy of the origin card that was cast (this is not the original card, so it's possible to chnage some attribute to this blueprint to change attributes to the permanent if it enters the battlefield with e.g. a subtype)
|
||||
protected Card card;
|
||||
// the number this permanent instance had
|
||||
protected int zoneChangeCounter;
|
||||
|
|
@ -141,6 +143,11 @@ public class PermanentCard extends PermanentImpl {
|
|||
this.flipCardName = card.getFlipCardName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageObject getBasicMageObject(Game game) {
|
||||
return card;
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
return card;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import mage.cards.CardImpl;
|
|||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.EffectType;
|
||||
import mage.constants.EnterEventType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.Counter;
|
||||
|
|
@ -872,12 +873,18 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
// remove some attributes here, because first apply effects comes later otherwise abilities (e.g. color related) will unintended trigger
|
||||
MorphAbility.setPermanentToFaceDownCreature(this);
|
||||
}
|
||||
EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone);
|
||||
|
||||
EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone, EnterEventType.SELF);
|
||||
if (game.replaceEvent(event)) {
|
||||
return false;
|
||||
}
|
||||
event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (fireEvent) {
|
||||
game.addSimultaneousEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
package mage.game.permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.game.Game;
|
||||
|
|
@ -92,6 +93,11 @@ public class PermanentToken extends PermanentImpl {
|
|||
this.tokenDescriptor = token.getTokenDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageObject getBasicMageObject(Game game) {
|
||||
return token;
|
||||
}
|
||||
|
||||
public Token getToken() {
|
||||
return token;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import mage.constants.CardType;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class GremlinToken extends Token {
|
||||
|
||||
public GremlinToken() {
|
||||
super("Gremlin", "2/2 red Gremlin creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
this.setOriginalExpansionSetCode("AER");
|
||||
subtype.add("Gremlin");
|
||||
color.setRed(true);
|
||||
power = new MageInt(2);
|
||||
toughness = new MageInt(2);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,6 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import mage.MageInt;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
}
|
||||
}
|
||||
setDoneActivatingManaAbilities(false); // can be activated again maybe during the resolution of the spell (e.g. Metallic Rebuke)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -256,8 +257,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
Permanent permanent = game.getPermanent(card.getId());
|
||||
if (permanent != null && permanent instanceof PermanentCard) {
|
||||
permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set
|
||||
((PermanentCard) permanent).getCard().getCardType().add(CardType.CREATURE);
|
||||
((PermanentCard) permanent).getCard().getSubtype(game).remove("Aura");
|
||||
card.getCardType().add(CardType.CREATURE);
|
||||
card.getSubtype(game).remove("Aura");
|
||||
}
|
||||
}
|
||||
return ability.resolve(game);
|
||||
|
|
@ -270,7 +271,15 @@ public class Spell extends StackObjImpl implements Card {
|
|||
// Aura has no legal target and its a bestow enchantment -> Add it to battlefield as creature
|
||||
if (this.getSpellAbility() instanceof BestowAbility) {
|
||||
updateOptionalCosts(0);
|
||||
return controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null);
|
||||
if (controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null)) {
|
||||
Permanent permanent = game.getPermanent(card.getId());
|
||||
if (permanent != null && permanent instanceof PermanentCard) {
|
||||
((PermanentCard) permanent).getCard().getCardType().add(CardType.CREATURE);
|
||||
((PermanentCard) permanent).getCard().getSubtype(game).remove("Aura");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
//20091005 - 608.2b
|
||||
if (!game.isSimulation()) {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public abstract class Phase implements Serializable {
|
|||
if (game.isPaused() || game.gameOver(null)) {
|
||||
return false;
|
||||
}
|
||||
if (game.getTurn().isEndTurnRequested() && !step.getType().equals(PhaseStep.CLEANUP)) {
|
||||
if (game.getTurn().isEndTurnRequested() && step.getType()!=PhaseStep.CLEANUP) {
|
||||
continue;
|
||||
}
|
||||
currentStep = step;
|
||||
|
|
|
|||
|
|
@ -208,9 +208,7 @@ public class Library implements Serializable {
|
|||
Map<String, Card> cards = new HashMap<>();
|
||||
for (UUID cardId : library) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (!cards.containsKey(card.getName())) {
|
||||
cards.put(card.getName(), card);
|
||||
}
|
||||
cards.putIfAbsent(card.getName(), card);
|
||||
}
|
||||
return cards.values();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,53 +29,22 @@ package mage.players;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.ConditionalMana;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.PlayLandAbility;
|
||||
import mage.abilities.SpecialAction;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.common.PassAbility;
|
||||
import mage.abilities.common.delayed.AtTheEndOfTurnStepPostDelayedTriggeredAbility;
|
||||
import mage.abilities.costs.AdjustingSourceCosts;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
||||
import mage.abilities.costs.*;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.RestrictionUntapNotMoreThanEffect;
|
||||
import mage.abilities.effects.common.LoseControlOnOtherPlayersControllerEffect;
|
||||
import mage.abilities.keyword.ConvokeAbility;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.abilities.keyword.InfectAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.abilities.keyword.ShroudAbility;
|
||||
import mage.abilities.keyword.*;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.abilities.mana.ManaOptions;
|
||||
import mage.actions.MageDrawAction;
|
||||
|
|
@ -84,17 +53,7 @@ import mage.cards.Cards;
|
|||
import mage.cards.CardsImpl;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.counters.Counters;
|
||||
|
|
@ -105,12 +64,7 @@ import mage.filter.common.FilterCreatureForCombat;
|
|||
import mage.filter.common.FilterCreatureForCombatBlock;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.PermanentIdPredicate;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.Graveyard;
|
||||
import mage.game.Table;
|
||||
import mage.game.ZoneChangeInfo;
|
||||
import mage.game.ZonesHandler;
|
||||
import mage.game.*;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.command.CommandObject;
|
||||
import mage.game.events.DamagePlayerEvent;
|
||||
|
|
@ -472,7 +426,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
/**
|
||||
* called before apply effects
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
|
|
@ -701,7 +654,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param amount
|
||||
* @param source
|
||||
* @param game
|
||||
|
|
@ -998,7 +950,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (game == null || ability == null) {
|
||||
return false;
|
||||
}
|
||||
if (!ability.getSpellAbilityType().equals(SpellAbilityType.BASE)) {
|
||||
if (ability.getSpellAbilityType() != SpellAbilityType.BASE) {
|
||||
ability = chooseSpellAbilityForCast(ability, game, noMana);
|
||||
}
|
||||
//20091005 - 601.2a
|
||||
|
|
@ -1221,7 +1173,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
//if player has taken an action then reset all player passed flags
|
||||
justActivatedType = null;
|
||||
if (result) {
|
||||
if (isHuman() && (ability.getAbilityType().equals(AbilityType.SPELL) || ability.getAbilityType().equals(AbilityType.ACTIVATED))) {
|
||||
if (isHuman() && (ability.getAbilityType() == AbilityType.SPELL || ability.getAbilityType() == AbilityType.ACTIVATED)) {
|
||||
if (ability.isUsesStack()) { // if the ability does not use the stack (e.g. Suspend) auto pass would go to next phase unintended
|
||||
setJustActivatedType(ability.getAbilityType());
|
||||
}
|
||||
|
|
@ -1269,8 +1221,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>();
|
||||
for (Ability ability : object.getAbilities()) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
if (((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) {
|
||||
if (zone.equals(Zone.HAND)) {
|
||||
if (((SpellAbility) ability).getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
|
||||
if (zone == Zone.HAND) {
|
||||
// Fix so you don't need to choose Fuse twice
|
||||
useable.clear();
|
||||
useable.put(ability.getId(), (SpellAbility) ability);
|
||||
|
|
@ -1280,7 +1232,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT)) {
|
||||
if (((SpellAbility) ability).getSpellAbilityType() == SpellAbilityType.SPLIT) {
|
||||
continue;
|
||||
}
|
||||
useable.put(ability.getId(), (SpellAbility) ability);
|
||||
|
|
@ -1297,7 +1249,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
// ManaOptions availableMana = getManaAvailable(game); // can only be activated if mana calculation works flawless otherwise player can't play spells they could play if calculation would work correctly
|
||||
// availableMana.addMana(manaPool.getMana());
|
||||
for (Ability ability : object.getAbilities()) {
|
||||
if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) {
|
||||
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.getZone().match(zone)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
if (ability instanceof ActivatedManaAbilityImpl) {
|
||||
|
|
@ -1320,9 +1272,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
if (zone != Zone.HAND) {
|
||||
if (Zone.GRAVEYARD.equals(zone) && canPlayCardsFromGraveyard()) {
|
||||
if (Zone.GRAVEYARD == zone && canPlayCardsFromGraveyard()) {
|
||||
for (ActivatedAbility ability : object.getAbilities().getPlayableAbilities(Zone.HAND)) {
|
||||
if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) {
|
||||
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.getManaCosts().isEmpty() && ability.getCosts().isEmpty() && ability instanceof SpellAbility) {
|
||||
continue; // You can't play spells from graveyard that have no costs
|
||||
}
|
||||
|
|
@ -1334,7 +1286,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
if (zone != Zone.BATTLEFIELD && game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
for (Ability ability : object.getAbilities()) {
|
||||
if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) {
|
||||
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.getManaCosts().isEmpty() && ability.getCosts().isEmpty() && ability instanceof SpellAbility && !(ability.getSourceId() == getCastSourceIdWithAlternateMana())) {
|
||||
continue; // You can't play spells that have no costs, unless you can play them without paying their mana costs
|
||||
}
|
||||
|
|
@ -1358,7 +1310,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (otherAbilities != null) {
|
||||
boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game);
|
||||
for (ActivatedAbility ability : otherAbilities) {
|
||||
if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) {
|
||||
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
Card card = game.getCard(ability.getSourceId());
|
||||
if (card.isSplitCard() && ability instanceof FlashbackAbility) {
|
||||
FlashbackAbility flashbackAbility;
|
||||
|
|
@ -1401,7 +1353,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
LinkedHashMap<UUID, ActivatedManaAbilityImpl> useable = new LinkedHashMap<>();
|
||||
boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game);
|
||||
for (ActivatedManaAbilityImpl ability : object.getAbilities().getActivatedManaAbilities(zone)) {
|
||||
if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) {
|
||||
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.canActivate(playerId, game)) {
|
||||
useable.put(ability.getId(), ability);
|
||||
}
|
||||
|
|
@ -2057,7 +2009,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
passedUntilEndOfTurn = true;
|
||||
passedUntilStackResolved = false;
|
||||
passedUntilEndStepBeforeMyTurn = false;
|
||||
skippedAtLeastOnce = !PhaseStep.END_TURN.equals(game.getTurn().getStepType());
|
||||
skippedAtLeastOnce = PhaseStep.END_TURN != game.getTurn().getStepType();
|
||||
this.skip();
|
||||
break;
|
||||
case PASS_PRIORITY_UNTIL_NEXT_TURN: // F4
|
||||
|
|
@ -2088,7 +2040,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
passedUntilNextMain = true;
|
||||
passedUntilStackResolved = false;
|
||||
passedUntilEndStepBeforeMyTurn = false;
|
||||
skippedAtLeastOnce = !(game.getTurn().getStepType().equals(PhaseStep.POSTCOMBAT_MAIN) || game.getTurn().getStepType().equals(PhaseStep.PRECOMBAT_MAIN));
|
||||
skippedAtLeastOnce = !(game.getTurn().getStepType() == PhaseStep.POSTCOMBAT_MAIN || game.getTurn().getStepType() == PhaseStep.PRECOMBAT_MAIN);
|
||||
this.skip();
|
||||
break;
|
||||
case PASS_PRIORITY_UNTIL_STACK_RESOLVED: //F8
|
||||
|
|
@ -2333,7 +2285,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
/**
|
||||
* @param game
|
||||
* @param appliedEffects
|
||||
*
|
||||
* @return true if player won the toss
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -2470,7 +2421,6 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ability
|
||||
* @param available if null, it won't be checked if enough mana is available
|
||||
* @param sourceObject
|
||||
|
|
@ -2608,7 +2558,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (!(sourceObject instanceof Permanent)) {
|
||||
Ability sourceAbility = null;
|
||||
for (Ability landAbility : sourceObject.getAbilities()) {
|
||||
if (landAbility.getAbilityType().equals(AbilityType.PLAY_LAND)) {
|
||||
if (landAbility.getAbilityType() == AbilityType.PLAY_LAND) {
|
||||
sourceAbility = landAbility;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2748,9 +2698,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
|
||||
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getUseableActivatedAbilities(permanent, Zone.BATTLEFIELD, game);
|
||||
for (ActivatedAbility ability : useableAbilities.values()) {
|
||||
if (!playableActivated.containsKey(ability.toString())) {
|
||||
playableActivated.put(ability.toString(), ability);
|
||||
}
|
||||
playableActivated.putIfAbsent(ability.toString(), ability);
|
||||
}
|
||||
}
|
||||
// activated abilities from stack objects
|
||||
|
|
@ -2781,10 +2729,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
* Creates a list of card ids that are currently playable.<br>
|
||||
* Used to mark the playable cards in GameView
|
||||
*
|
||||
* @return A Set of cardIds that are playable
|
||||
*
|
||||
* @param game
|
||||
*
|
||||
* @return A Set of cardIds that are playable
|
||||
*/
|
||||
@Override
|
||||
public Set<UUID> getPlayableInHand(Game game
|
||||
|
|
@ -3191,8 +3137,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
case HAND:
|
||||
for (Card card : cards) {
|
||||
fromZone = game.getState().getZone(card.getId());
|
||||
boolean hideCard = fromZone.equals(Zone.LIBRARY)
|
||||
|| (card.isFaceDown(game) && !fromZone.equals(Zone.STACK) && !fromZone.equals(Zone.BATTLEFIELD));
|
||||
boolean hideCard = fromZone == Zone.LIBRARY
|
||||
|| (card.isFaceDown(game) && fromZone != Zone.STACK && fromZone != Zone.BATTLEFIELD);
|
||||
if (moveCardToHandWithInfo(card, source == null ? null : source.getSourceId(), game, !hideCard)) {
|
||||
successfulMovedCards.add(card);
|
||||
}
|
||||
|
|
@ -3201,7 +3147,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
case EXILED:
|
||||
for (Card card : cards) {
|
||||
fromZone = game.getState().getZone(card.getId());
|
||||
boolean withName = (fromZone.equals(Zone.BATTLEFIELD) || fromZone.equals(Zone.STACK)) || !card.isFaceDown(game);
|
||||
boolean withName = (fromZone == Zone.BATTLEFIELD || fromZone == Zone.STACK) || !card.isFaceDown(game);
|
||||
if (moveCardToExileWithInfo(card, null, "", source == null ? null : source.getSourceId(), game, fromZone, withName)) {
|
||||
successfulMovedCards.add(card);
|
||||
}
|
||||
|
|
@ -3214,7 +3160,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
} else {
|
||||
fromZone = game.getState().getZone(card.getId());
|
||||
}
|
||||
boolean hideCard = fromZone.equals(Zone.HAND) || fromZone.equals(Zone.LIBRARY);
|
||||
boolean hideCard = fromZone == Zone.HAND || fromZone == Zone.LIBRARY;
|
||||
if (moveCardToLibraryWithInfo(card, source == null ? null : source.getSourceId(), game, fromZone, true, !hideCard)) {
|
||||
successfulMovedCards.add(card);
|
||||
}
|
||||
|
|
@ -3255,7 +3201,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game, boolean withName) {
|
||||
boolean result = false;
|
||||
Zone fromZone = game.getState().getZone(card.getId());
|
||||
if (fromZone.equals(Zone.BATTLEFIELD) && !(card instanceof Permanent)) {
|
||||
if (fromZone == Zone.BATTLEFIELD && !(card instanceof Permanent)) {
|
||||
card = game.getPermanent(card.getId());
|
||||
}
|
||||
if (card.moveToZone(Zone.HAND, sourceId, game, false)) {
|
||||
|
|
@ -3345,7 +3291,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, Game game, Zone fromZone) {
|
||||
boolean result = false;
|
||||
// Zone fromZone = game.getState().getZone(card.getId());
|
||||
if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null ? fromZone.equals(Zone.BATTLEFIELD) : false)) {
|
||||
if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null ? fromZone == Zone.BATTLEFIELD : false)) {
|
||||
if (!game.isSimulation()) {
|
||||
if (card instanceof PermanentCard && game.getCard(card.getId()) != null) {
|
||||
card = game.getCard(card.getId());
|
||||
|
|
@ -3406,7 +3352,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
card = basicCard;
|
||||
}
|
||||
}
|
||||
game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName() : "a card face down") + " "
|
||||
game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName() + (card.isCopy() ? " (Copy)" : "") : "a card face down") + " "
|
||||
+ (fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + " " : "") + "to the exile zone");
|
||||
}
|
||||
result = true;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -49,7 +50,6 @@ import mage.players.Player;
|
|||
import mage.util.RandomUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public abstract class TargetImpl implements Target {
|
||||
|
|
@ -184,7 +184,7 @@ public abstract class TargetImpl implements Target {
|
|||
|
||||
@Override
|
||||
public boolean isRequired(Ability ability) {
|
||||
return ability == null || ability.isActivated() || !(ability.getAbilityType().equals(AbilityType.SPELL) || ability.getAbilityType().equals(AbilityType.ACTIVATED));
|
||||
return ability == null || ability.isActivated() || !(ability.getAbilityType() == AbilityType.SPELL || ability.getAbilityType() == AbilityType.ACTIVATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -132,6 +132,6 @@ public class TargetSpell extends TargetObject {
|
|||
private boolean canBeChosen(StackObject stackObject, UUID sourceID, UUID sourceControllerId, Game game) {
|
||||
return stackObject instanceof Spell
|
||||
&& game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId())
|
||||
&& filter.match((Spell) stackObject, sourceID, sourceControllerId, game);
|
||||
&& filter.match(stackObject, sourceID, sourceControllerId, game);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
package mage.target.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,9 @@
|
|||
*/
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.TargetController;
|
||||
import mage.abilities.Ability;
|
||||
import mage.filter.FilterPlayer;
|
||||
import mage.filter.predicate.other.PlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
/**
|
||||
|
|
@ -56,16 +53,6 @@ public class TargetOpponent extends TargetPlayer {
|
|||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
return super.canChoose(sourceId, sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
return super.canTarget(id, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetOpponent copy() {
|
||||
return new TargetOpponent(this);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public class CardUtil {
|
|||
|
||||
private static final String SOURCE_EXILE_ZONE_TEXT = "SourceExileZone";
|
||||
|
||||
static String numberStrings[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
static final String[] numberStrings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "ninteen", "twenty"};
|
||||
|
||||
public static final String[] NON_CHANGELING_SUBTYPES_VALUES = new String[]{
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||
public class CircularList<E> implements List<E>, Iterable<E>, Serializable {
|
||||
//TODO: might have to make E extend Copyable
|
||||
|
||||
protected List<E> list = new ArrayList<>();
|
||||
protected final List<E> list = new ArrayList<>();
|
||||
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
|
|
@ -357,8 +357,8 @@ public class CircularList<E> implements List<E>, Iterable<E>, Serializable {
|
|||
private class CircularIterator<E> implements Iterator<E> {
|
||||
|
||||
int cursor;
|
||||
int lastIndex;
|
||||
int curModCount;
|
||||
final int lastIndex;
|
||||
final int curModCount;
|
||||
boolean hasMoved = false;
|
||||
|
||||
private CircularIterator() {
|
||||
|
|
@ -399,9 +399,9 @@ public class CircularList<E> implements List<E>, Iterable<E>, Serializable {
|
|||
private class CircularListIterator<E> implements ListIterator<E> {
|
||||
|
||||
int cursor;
|
||||
int lastIndex;
|
||||
int firstIndex;
|
||||
int curModCount;
|
||||
final int lastIndex;
|
||||
final int firstIndex;
|
||||
final int curModCount;
|
||||
boolean hasMoved = false;
|
||||
|
||||
private CircularListIterator() {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.StreamCorruptedException;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ import mage.target.Target;
|
|||
*/
|
||||
public class TargetAddress {
|
||||
|
||||
protected int spellAbilityIndex;
|
||||
protected UUID mode;
|
||||
protected int targetIndex;
|
||||
protected final int spellAbilityIndex;
|
||||
protected final UUID mode;
|
||||
protected final int targetIndex;
|
||||
|
||||
public TargetAddress(int spellAbilityIndex, UUID mode, int targetIndex) {
|
||||
this.spellAbilityIndex = spellAbilityIndex;
|
||||
|
|
@ -68,7 +68,7 @@ public class TargetAddress {
|
|||
|
||||
protected static class TargetAddressIterator implements Iterator<TargetAddress> {
|
||||
|
||||
protected Iterator<SpellAbility> spellAbilityIterator;
|
||||
protected final Iterator<SpellAbility> spellAbilityIterator;
|
||||
protected Integer lastSpellAbilityIndex = null;
|
||||
protected Iterator<UUID> modeIterator = null;
|
||||
protected Modes modes = null;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ package mage.util;
|
|||
*/
|
||||
public class ThreadLocalStringBuilder extends ThreadLocal<StringBuilder> {
|
||||
|
||||
private int size;
|
||||
private final int size;
|
||||
|
||||
public ThreadLocalStringBuilder(int size) {
|
||||
this.size = size;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public abstract class Watcher implements Serializable {
|
|||
this.controllerId = watcher.controllerId;
|
||||
this.sourceId = watcher.sourceId;
|
||||
this.scope = watcher.scope;
|
||||
this.basicKey = watcher.basicKey;
|
||||
}
|
||||
|
||||
public UUID getControllerId() {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
package mage.watchers;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
|
@ -43,7 +42,7 @@ public class Watchers extends HashMap<String, Watcher> {
|
|||
}
|
||||
|
||||
public Watchers(final Watchers watchers) {
|
||||
watchers.entrySet().stream().forEach((entry) -> this.put(entry.getKey(), entry.getValue().copy()));
|
||||
watchers.entrySet().forEach((entry) -> this.put(entry.getKey(), entry.getValue().copy()));
|
||||
}
|
||||
|
||||
public Watchers copy() {
|
||||
|
|
@ -51,9 +50,7 @@ public class Watchers extends HashMap<String, Watcher> {
|
|||
}
|
||||
|
||||
public void add(Watcher watcher) {
|
||||
if (!this.containsKey(watcher.getKey())) {
|
||||
this.put(watcher.getKey(), watcher);
|
||||
}
|
||||
putIfAbsent(watcher.getKey(), watcher);
|
||||
}
|
||||
|
||||
public void watch(GameEvent event, Game game) {
|
||||
|
|
@ -63,7 +60,7 @@ public class Watchers extends HashMap<String, Watcher> {
|
|||
}
|
||||
|
||||
public void reset() {
|
||||
this.values().stream().forEach(Watcher::reset);
|
||||
this.values().forEach(Watcher::reset);
|
||||
}
|
||||
|
||||
public Watcher get(String key, UUID id) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -80,7 +81,7 @@ public class CardsPutIntoGraveyardWatcher extends Watcher {
|
|||
++amount;
|
||||
}
|
||||
amountOfCardsThisTurn.put(playerId, amount);
|
||||
if (((ZoneChangeEvent) event).getFromZone().equals(Zone.BATTLEFIELD)) {
|
||||
if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
|
||||
cardsPutToGraveyardFromBattlefield.add(new MageObjectReference(event.getTargetId(), game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,11 +66,7 @@ public class CastFromGraveyardWatcher extends Watcher {
|
|||
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone().equals(Zone.GRAVEYARD)) {
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell != null) {
|
||||
HashSet<Integer> zcc = spellsCastFromGraveyard.get(spell.getSourceId());
|
||||
if (zcc == null) {
|
||||
zcc = new HashSet<>();
|
||||
spellsCastFromGraveyard.put(spell.getSourceId(), zcc);
|
||||
}
|
||||
HashSet<Integer> zcc = spellsCastFromGraveyard.computeIfAbsent(spell.getSourceId(), k -> new HashSet<>());
|
||||
zcc.add(spell.getZoneChangeCounter(game));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,9 +64,4 @@ public class FirstTimeStepWatcher extends Watcher {
|
|||
condition = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue