Merge pull request #1 from magefree/master

getting upstream
This commit is contained in:
brodee 2018-11-04 19:20:46 -08:00 committed by GitHub
commit c6702ca9eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 589 additions and 122 deletions

View file

@ -214,7 +214,7 @@ public class CallbackClientImpl implements CallbackClient {
case GAME_CHOOSE_ABILITY: { case GAME_CHOOSE_ABILITY: {
GamePanel panel = MageFrame.getGame(callback.getObjectId()); GamePanel panel = MageFrame.getGame(callback.getObjectId());
if (panel != null) { if (panel != null) {
appendJsonEvent("GAME_CHOOSE_PILE", callback.getObjectId(), callback.getData()); appendJsonEvent("GAME_CHOOSE_ABILITY", callback.getObjectId(), callback.getData());
panel.pickAbility((AbilityPickerView) callback.getData()); panel.pickAbility((AbilityPickerView) callback.getData());
} }
break; break;

View file

@ -1,15 +1,15 @@
package mage.deck; package mage.deck;
import java.util.HashMap;
import java.util.Map;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType; import mage.constants.SetType;
import java.util.HashMap;
import java.util.Map;
/** /**
*
* @author spjspj * @author spjspj
*/ */
public class AusHighlander extends Constructed { public class AusHighlander extends Constructed {
@ -36,9 +36,9 @@ public class AusHighlander extends Constructed {
pointMap.put("Dig Through Time", 2); pointMap.put("Dig Through Time", 2);
pointMap.put("Library of Alexandria", 2); pointMap.put("Library of Alexandria", 2);
pointMap.put("Mana Crypt", 2); pointMap.put("Mana Crypt", 2);
pointMap.put("Mind Twist", 2);
pointMap.put("Mystical Tutor", 2); pointMap.put("Mystical Tutor", 2);
pointMap.put("Protean Hulk", 2); pointMap.put("Protean Hulk", 2);
pointMap.put("Skullclamp", 2);
pointMap.put("Strip Mine", 2); pointMap.put("Strip Mine", 2);
pointMap.put("Tolarian Academy", 2); pointMap.put("Tolarian Academy", 2);
pointMap.put("Treasure Cruise", 2); pointMap.put("Treasure Cruise", 2);
@ -61,12 +61,12 @@ public class AusHighlander extends Constructed {
pointMap.put("Mana Vault", 1); pointMap.put("Mana Vault", 1);
pointMap.put("Memory Jar", 1); pointMap.put("Memory Jar", 1);
pointMap.put("Merchant Scroll", 1); pointMap.put("Merchant Scroll", 1);
pointMap.put("Mind Twist", 1);
pointMap.put("Mishras Workshop", 1); pointMap.put("Mishras Workshop", 1);
pointMap.put("Natural Order", 1); pointMap.put("Natural Order", 1);
pointMap.put("Oath of Druids", 1); pointMap.put("Oath of Druids", 1);
pointMap.put("Personal Tutor", 1); pointMap.put("Personal Tutor", 1);
pointMap.put("Senseis Divining Top", 1); pointMap.put("Senseis Divining Top", 1);
pointMap.put("Skullclamp", 1);
pointMap.put("Snapcaster Mage", 1); pointMap.put("Snapcaster Mage", 1);
pointMap.put("Stoneforge Mystic", 1); pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Survival of the Fittest", 1); pointMap.put("Survival of the Fittest", 1);

View file

@ -1,15 +1,15 @@
package mage.deck; package mage.deck;
import java.util.HashMap;
import java.util.Map;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.constants.SetType; import mage.constants.SetType;
import java.util.HashMap;
import java.util.Map;
/** /**
*
* @author spjspj * @author spjspj
*/ */
public class CanadianHighlander extends Constructed { public class CanadianHighlander extends Constructed {
@ -19,7 +19,7 @@ public class CanadianHighlander extends Constructed {
static { static {
pointMap.put("Ancestral Recall", 7); pointMap.put("Ancestral Recall", 7);
pointMap.put("Balance", 1); pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 3); pointMap.put("Birthing Pod", 2);
pointMap.put("Black Lotus", 7); pointMap.put("Black Lotus", 7);
pointMap.put("Demonic Tutor", 3); pointMap.put("Demonic Tutor", 3);
pointMap.put("Dig Through Time", 1); pointMap.put("Dig Through Time", 1);
@ -27,7 +27,6 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Fastbond", 1); pointMap.put("Fastbond", 1);
pointMap.put("Flash", 7); pointMap.put("Flash", 7);
pointMap.put("Gifts Ungiven", 2); pointMap.put("Gifts Ungiven", 2);
pointMap.put("Hermit Druid", 1);
pointMap.put("Imperial Seal", 1); pointMap.put("Imperial Seal", 1);
pointMap.put("Intuition", 1); pointMap.put("Intuition", 1);
pointMap.put("Library of Alexandria", 1); pointMap.put("Library of Alexandria", 1);

View file

@ -135,7 +135,7 @@ class CelestialDawnToWhiteEffect extends ContinuousEffectImpl {
// Command // Command
for (CommandObject commandObject : game.getState().getCommand()) { for (CommandObject commandObject : game.getState().getCommand()) {
if (commandObject instanceof Commander) { if (commandObject instanceof Commander) {
if (commandObject.getControllerId().equals(controller.getId())) { if (commandObject.isControlledBy(controller.getId())) {
setColor(commandObject.getColor(game), game); setColor(commandObject.getColor(game), game);
} }
} }

View file

@ -0,0 +1,92 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Library;
import mage.players.Player;
/**
*
* @author davidmfritz
*/
public final class ClearTheLand extends CardImpl {
public ClearTheLand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
// Each player reveals the top five cards of his or her library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest.
getSpellAbility().addEffect(new ClearTheLandEffect());
}
public ClearTheLand(final ClearTheLand card) {
super(card);
}
@Override
public ClearTheLand copy() {
return new ClearTheLand(this);
}
}
class ClearTheLandEffect extends OneShotEffect {
public ClearTheLandEffect() {
super(Outcome.Benefit);
this.staticText = "Each player reveals the top five cards of his or her library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest.";
}
public ClearTheLandEffect(final ClearTheLandEffect effect) {
super(effect);
}
@Override
public ClearTheLandEffect copy() {
return new ClearTheLandEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
boolean tapped = true;
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
Library library = player.getLibrary();
Cards cardsToReveal = new CardsImpl();
cardsToReveal.addAll(library.getTopCards(game, 5));
if (!cardsToReveal.isEmpty()) {
player.revealCards(source, "Revealed cards for " + player.getName(), cardsToReveal, game);
Cards cardsToPutOnBattlefield = new CardsImpl();
Cards cardsToExile = new CardsImpl();
for (Card card : cardsToReveal.getCards(game)) {
if (card.isLand()) {
cardsToPutOnBattlefield.add(card);
} else {
cardsToExile.add(card);
}
}
player.moveCards(cardsToPutOnBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, tapped, false, true, null);
player.moveCards(cardsToExile.getCards(game), Zone.EXILED, source, game);
}
}
}
return true;
}
return false;
}
}

View file

@ -88,7 +88,7 @@ class CoverOfWinterEffect extends PreventionEffectImpl {
if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) { if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) {
Permanent permanent = game.getPermanent(event.getTargetId()); Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { if (permanent != null && permanent.isControlledBy(source.getControllerId())) {
return super.applies(event, source, game); return super.applies(event, source, game);
} }
} }

View file

@ -94,11 +94,11 @@ class EmissaryOfGrudgesEffect extends OneShotEffect {
Mode mode = stackObject.getStackAbility().getModes().get(modeId); Mode mode = stackObject.getStackAbility().getModes().get(modeId);
for (Target target : mode.getTargets()) { for (Target target : mode.getTargets()) {
for (UUID targetId : target.getTargets()) { for (UUID targetId : target.getTargets()) {
if (source.getControllerId().equals(targetId)) { if (source.isControlledBy(targetId)) {
targetsYouOrAPermanentYouControl = true; targetsYouOrAPermanentYouControl = true;
} }
Permanent permanent = game.getPermanent(targetId); Permanent permanent = game.getPermanent(targetId);
if (permanent != null && source.getControllerId().equals(permanent.getControllerId())) { if (permanent != null && source.isControlledBy(permanent.getControllerId())) {
targetsYouOrAPermanentYouControl = true; targetsYouOrAPermanentYouControl = true;
} }
} }

View file

@ -0,0 +1,73 @@
package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.ControllerPlaysLandTriggeredAbility;
import mage.abilities.common.OpponentPlaysLandTriggeredAbility;
import mage.abilities.condition.common.SourceMatchesFilterCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
import mage.abilities.effects.common.continuous.BecomesEnchantmentSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.permanent.token.TokenImpl;
/**
*
* @author jeffwadsworth
*/
public final class HiddenStag extends CardImpl {
public HiddenStag(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
// Whenever an opponent plays a land, if Hidden Stag is an enchantment, Hidden Stag becomes a 3/2 Elk Beast creature.
Effect effect = new BecomesCreatureSourceEffect(new ElkBeastToken(), "", Duration.WhileOnBattlefield, true, false);
TriggeredAbility ability = new OpponentPlaysLandTriggeredAbility(Zone.BATTLEFIELD, effect, false);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT),
"Whenever an opponent plays a land, if Hidden Stag is an enchantment, Hidden Stag becomes a 3/2 Elk Beast creature."));
// Whenever you play a land, if Hidden Stag is a creature, Hidden Stag becomes an enchantment.
Effect effect2 = new BecomesEnchantmentSourceEffect();
TriggeredAbility ability2 = new ControllerPlaysLandTriggeredAbility(Zone.BATTLEFIELD, effect2, false);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_CREATURE),
"Whenever you play a land, if Hidden Stag is a creature, Hidden Stag becomes an enchantment."));
}
public HiddenStag(final HiddenStag card) {
super(card);
}
@Override
public HiddenStag copy() {
return new HiddenStag(this);
}
}
class ElkBeastToken extends TokenImpl {
public ElkBeastToken() {
super("Elk Beast", "3/2 Elk Beast creature");
cardType.add(CardType.CREATURE);
subtype.add(SubType.ELK);
subtype.add(SubType.BEAST);
power = new MageInt(3);
toughness = new MageInt(2);
}
public ElkBeastToken(final ElkBeastToken token) {
super(token);
}
public ElkBeastToken copy() {
return new ElkBeastToken(this);
}
}

View file

@ -2,33 +2,23 @@ package mage.cards.o;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility;
import mage.abilities.condition.common.SourceMatchesFilterCondition; import mage.abilities.condition.common.SourceMatchesFilterCondition;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
import mage.abilities.effects.common.continuous.SourceEffect; import mage.abilities.effects.common.continuous.BecomesEnchantmentSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Layer;
import static mage.constants.Layer.TypeChangingEffects_4;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterSpell; import mage.filter.FilterSpell;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TokenImpl; import mage.game.permanent.token.TokenImpl;
/** /**
@ -53,7 +43,7 @@ public final class OpalAcrolith extends CardImpl {
"Whenever an opponent casts a creature spell, if Opal Acrolith is an enchantment, Opal Acrolith becomes a 2/4 Soldier creature.")); "Whenever an opponent casts a creature spell, if Opal Acrolith is an enchantment, Opal Acrolith becomes a 2/4 Soldier creature."));
// {0}: Opal Acrolith becomes an enchantment. // {0}: Opal Acrolith becomes an enchantment.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesEnchantmentSourceEffect(CardType.ENCHANTMENT), new ManaCostsImpl("{0}"))); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesEnchantmentSourceEffect(), new ManaCostsImpl("{0}")));
} }
@ -67,63 +57,6 @@ public final class OpalAcrolith extends CardImpl {
} }
} }
class BecomesEnchantmentSourceEffect extends ContinuousEffectImpl implements SourceEffect {
public BecomesEnchantmentSourceEffect(CardType cardType) {
super(Duration.Custom, Outcome.AddAbility);
staticText = "Opal Acrolith becomes an Enchantment";
dependencyTypes.add(DependencyType.EnchantmentAddingRemoving);
}
public BecomesEnchantmentSourceEffect(final BecomesEnchantmentSourceEffect effect) {
super(effect);
}
@Override
public BecomesEnchantmentSourceEffect copy() {
return new BecomesEnchantmentSourceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
affectedObjectList.add(new MageObjectReference(source.getSourceId(), game));
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = affectedObjectList.get(0).getPermanent(game);
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getCardType().clear();
permanent.getSubtype(game).clear();
if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) {
permanent.getCardType().add(CardType.ENCHANTMENT);
}
}
break;
}
return true;
}
this.discard();
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return Layer.TypeChangingEffects_4 == layer;
}
}
class OpalAcrolithSoldier extends TokenImpl { class OpalAcrolithSoldier extends TokenImpl {
public OpalAcrolithSoldier() { public OpalAcrolithSoldier() {

View file

@ -69,7 +69,7 @@ class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl implements Sou
public OpalTitanBecomesCreatureEffect() { public OpalTitanBecomesCreatureEffect() {
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
setText(); staticText = "{this} becomes a 4/4 Giant creature with protection from each of that spell's colors.";
this.addDependencyType(DependencyType.BecomeCreature); this.addDependencyType(DependencyType.BecomeCreature);
} }
@ -135,10 +135,6 @@ class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl implements Sou
return false; return false;
} }
private void setText() {
staticText = duration.toString() + " {this} becomes a 4/4 Giant creature with protection from each of that spell's colors";
}
@Override @Override
public boolean hasLayer(Layer layer) { public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7 return layer == Layer.PTChangingEffects_7

View file

@ -2,24 +2,30 @@ package mage.cards.p;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromExileForSourceEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SetTargetPointer; import mage.constants.SetTargetPointer;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil; import mage.util.CardUtil;
/** /**
@ -34,14 +40,14 @@ public final class Portcullis extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature. // Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature.
String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature";
TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(), filter, false, SetTargetPointer.PERMANENT, rule);
MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule));
// Return that card to the battlefield under its owner's control when Portcullis leaves the battlefield. // Return that card to the battlefield under its owner's control when Portcullis leaves the battlefield.
Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false); String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature.";
this.addAbility(ability2); String rule2 = " Return that card to the battlefield under its owner's control when {this} leaves the battlefield.";
TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(),
filter, false, SetTargetPointer.PERMANENT, rule);
MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule + rule2));
} }
public Portcullis(final Portcullis card) { public Portcullis(final Portcullis card) {
@ -74,8 +80,8 @@ class MoreThanXCreaturesOnBFCondition implements Condition {
class PortcullisExileEffect extends OneShotEffect { class PortcullisExileEffect extends OneShotEffect {
public PortcullisExileEffect() { public PortcullisExileEffect() {
super(Outcome.Neutral); super(Outcome.Exile);
this.staticText = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature."; this.staticText = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature";
} }
public PortcullisExileEffect(final PortcullisExileEffect effect) { public PortcullisExileEffect(final PortcullisExileEffect effect) {
@ -89,20 +95,58 @@ class PortcullisExileEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source)); Permanent creatureToExile = game.getPermanent(getTargetPointer().getFirst(game, source));
Permanent portcullis = game.getPermanent(source.getSourceId());
Permanent permanent = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId());
if (permanent == null) { if (portcullis != null
permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); && creatureToExile != null
&& controller != null) {
UUID exileZoneId = CardUtil.getExileZoneId(game, creatureToExile.getId(), creatureToExile.getZoneChangeCounter(game));
controller.moveCardsToExile(creatureToExile, source, game, true, exileZoneId, portcullis.getName());
FixedTarget fixedTarget = new FixedTarget(portcullis, game);
Effect returnEffect = new ReturnToBattlefieldUnderOwnerControlTargetEffect();
returnEffect.setTargetPointer(new FixedTarget(creatureToExile.getId(), game.getState().getZoneChangeCounter(creatureToExile.getId())));
DelayedTriggeredAbility delayedAbility = new PortcullisReturnToBattlefieldTriggeredAbility(fixedTarget, returnEffect);
game.addDelayedTriggeredAbility(delayedAbility, source);
} }
if (permanent != null && creature != null) { return true;
Player controller = game.getPlayer(creature.getControllerId()); }
Zone currentZone = game.getState().getZone(creature.getId()); }
if (currentZone == Zone.BATTLEFIELD) {
controller.moveCardsToExile(creature, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName()); class PortcullisReturnToBattlefieldTriggeredAbility extends DelayedTriggeredAbility {
return true;
} protected FixedTarget fixedTarget;
public PortcullisReturnToBattlefieldTriggeredAbility(FixedTarget fixedTarget, Effect effect) {
super(effect, Duration.OneUse);
this.fixedTarget = fixedTarget;
}
public PortcullisReturnToBattlefieldTriggeredAbility(final PortcullisReturnToBattlefieldTriggeredAbility ability) {
super(ability);
this.fixedTarget = ability.fixedTarget;
}
@Override
public PortcullisReturnToBattlefieldTriggeredAbility copy() {
return new PortcullisReturnToBattlefieldTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (((ZoneChangeEvent) event).getFromZone().match(Zone.BATTLEFIELD)) {
return (fixedTarget.getTarget().equals(event.getTargetId()));
} }
return false; return false;
} }
@Override
public String getRule() {
return "Return this card to the battlefield under its owner's control when Portcullis leaves the battlefield.";
}
} }

View file

@ -100,7 +100,7 @@ class SavageSummoningAsThoughEffect extends AsThoughEffectImpl {
MageObject mageObject = game.getBaseObject(objectId); MageObject mageObject = game.getBaseObject(objectId);
if (mageObject instanceof Commander) { if (mageObject instanceof Commander) {
Commander commander = (Commander) mageObject; Commander commander = (Commander) mageObject;
if (commander.isCreature() && commander.getControllerId().equals(source.getControllerId())) { if (commander.isCreature() && commander.isControlledBy(source.getControllerId())) {
return true; return true;
} }
} else if (mageObject instanceof Card) { } else if (mageObject instanceof Card) {

View file

@ -5,7 +5,6 @@ import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -25,8 +24,7 @@ public final class ScepterOfEmpires extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// {tap}: Scepter of Empires deals 1 damage to target player. It deals 3 damage to that player instead if you control artifacts named Crown of Empires and Throne of Empires. // {tap}: Scepter of Empires deals 1 damage to target player. It deals 3 damage to that player instead if you control artifacts named Crown of Empires and Throne of Empires.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScepterOfEmpiresEffect(), new GenericManaCost(0)); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScepterOfEmpiresEffect(), new TapSourceCost());
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayerOrPlaneswalker()); ability.addTarget(new TargetPlayerOrPlaneswalker());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -0,0 +1,149 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import static mage.constants.Layer.TypeChangingEffects_4;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author jeffwadsworth
*/
public final class SoulSculptor extends CardImpl {
final String rule = "Target creature becomes an enchantment and loses all abilities until a player casts a creature spell.";
public SoulSculptor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {1}{W}, {tap}: Target creature becomes an enchantment and loses all abilities until a player casts a creature spell.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new SoulSculptorEffect(), SoulSculptorCondition.instance, rule), new ManaCostsImpl("{1}{W}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
public SoulSculptor(final SoulSculptor card) {
super(card);
}
@Override
public SoulSculptor copy() {
return new SoulSculptor(this);
}
}
class SoulSculptorEffect extends ContinuousEffectImpl {
public SoulSculptorEffect() {
super(Duration.Custom, Outcome.LoseAbility);
staticText = "target becomes an Enchantment and loses all abilites";
dependencyTypes.add(DependencyType.EnchantmentAddingRemoving);
dependencyTypes.add(DependencyType.AddingAbility);
}
public SoulSculptorEffect(final SoulSculptorEffect effect) {
super(effect);
}
@Override
public SoulSculptorEffect copy() {
return new SoulSculptorEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
Permanent targetPermanent = game.getPermanent(source.getFirstTarget());
if (targetPermanent != null) {
affectedObjectList.add(new MageObjectReference(targetPermanent, game));
}
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = affectedObjectList.get(0).getPermanent(game);
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getCardType().clear();
permanent.getSubtype(game).clear();
if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) {
permanent.getCardType().add(CardType.ENCHANTMENT);
}
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
permanent.getAbilities().clear();
}
break;
}
return true;
}
this.discard();
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return Layer.TypeChangingEffects_4 == layer
|| Layer.AbilityAddingRemovingEffects_6 == layer;
}
}
enum SoulSculptorCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
if (!game.getStack().isEmpty()) {
StackObject stackObject = game.getStack().getFirst();
if (stackObject != null) {
return !stackObject.getCardType().contains(CardType.CREATURE);
}
}
return true;
}
@Override
public String toString() {
return "creature spell cast";
}
}

View file

@ -75,6 +75,7 @@ public final class MercadianMasques extends ExpansionSet {
cards.add(new SetCardInfo("Cho-Manno, Revolutionary", 11, Rarity.RARE, mage.cards.c.ChoMannoRevolutionary.class)); cards.add(new SetCardInfo("Cho-Manno, Revolutionary", 11, Rarity.RARE, mage.cards.c.ChoMannoRevolutionary.class));
cards.add(new SetCardInfo("Cho-Manno's Blessing", 12, Rarity.COMMON, mage.cards.c.ChoMannosBlessing.class)); cards.add(new SetCardInfo("Cho-Manno's Blessing", 12, Rarity.COMMON, mage.cards.c.ChoMannosBlessing.class));
cards.add(new SetCardInfo("Cinder Elemental", 183, Rarity.UNCOMMON, mage.cards.c.CinderElemental.class)); cards.add(new SetCardInfo("Cinder Elemental", 183, Rarity.UNCOMMON, mage.cards.c.CinderElemental.class));
cards.add(new SetCardInfo("Clear the Land", 235, Rarity.RARE, mage.cards.c.ClearTheLand.class));
cards.add(new SetCardInfo("Close Quarters", 184, Rarity.UNCOMMON, mage.cards.c.CloseQuarters.class)); cards.add(new SetCardInfo("Close Quarters", 184, Rarity.UNCOMMON, mage.cards.c.CloseQuarters.class));
cards.add(new SetCardInfo("Cloud Sprite", 67, Rarity.COMMON, mage.cards.c.CloudSprite.class)); cards.add(new SetCardInfo("Cloud Sprite", 67, Rarity.COMMON, mage.cards.c.CloudSprite.class));
cards.add(new SetCardInfo("Coastal Piracy", 68, Rarity.UNCOMMON, mage.cards.c.CoastalPiracy.class)); cards.add(new SetCardInfo("Coastal Piracy", 68, Rarity.UNCOMMON, mage.cards.c.CoastalPiracy.class));

View file

@ -164,6 +164,7 @@ public final class UrzasSaga extends ExpansionSet {
cards.add(new SetCardInfo("Hidden Guerrillas", 261, Rarity.UNCOMMON, mage.cards.h.HiddenGuerrillas.class)); cards.add(new SetCardInfo("Hidden Guerrillas", 261, Rarity.UNCOMMON, mage.cards.h.HiddenGuerrillas.class));
cards.add(new SetCardInfo("Hidden Herd", 262, Rarity.RARE, mage.cards.h.HiddenHerd.class)); cards.add(new SetCardInfo("Hidden Herd", 262, Rarity.RARE, mage.cards.h.HiddenHerd.class));
cards.add(new SetCardInfo("Hidden Spider", 264, Rarity.COMMON, mage.cards.h.HiddenSpider.class)); cards.add(new SetCardInfo("Hidden Spider", 264, Rarity.COMMON, mage.cards.h.HiddenSpider.class));
cards.add(new SetCardInfo("Hidden Stag", 265, Rarity.RARE, mage.cards.h.HiddenStag.class));
cards.add(new SetCardInfo("Hollow Dogs", 137, Rarity.COMMON, mage.cards.h.HollowDogs.class)); cards.add(new SetCardInfo("Hollow Dogs", 137, Rarity.COMMON, mage.cards.h.HollowDogs.class));
cards.add(new SetCardInfo("Hopping Automaton", 297, Rarity.UNCOMMON, mage.cards.h.HoppingAutomaton.class)); cards.add(new SetCardInfo("Hopping Automaton", 297, Rarity.UNCOMMON, mage.cards.h.HoppingAutomaton.class));
cards.add(new SetCardInfo("Horseshoe Crab", 80, Rarity.COMMON, mage.cards.h.HorseshoeCrab.class)); cards.add(new SetCardInfo("Horseshoe Crab", 80, Rarity.COMMON, mage.cards.h.HorseshoeCrab.class));
@ -295,6 +296,7 @@ public final class UrzasSaga extends ExpansionSet {
cards.add(new SetCardInfo("Sneak Attack", 218, Rarity.RARE, mage.cards.s.SneakAttack.class)); cards.add(new SetCardInfo("Sneak Attack", 218, Rarity.RARE, mage.cards.s.SneakAttack.class));
cards.add(new SetCardInfo("Somnophore", 97, Rarity.RARE, mage.cards.s.Somnophore.class)); cards.add(new SetCardInfo("Somnophore", 97, Rarity.RARE, mage.cards.s.Somnophore.class));
cards.add(new SetCardInfo("Songstitcher", 52, Rarity.UNCOMMON, mage.cards.s.Songstitcher.class)); cards.add(new SetCardInfo("Songstitcher", 52, Rarity.UNCOMMON, mage.cards.s.Songstitcher.class));
cards.add(new SetCardInfo("Soul Sculptor", 53, Rarity.RARE, mage.cards.s.SoulSculptor.class));
cards.add(new SetCardInfo("Spined Fluke", 160, Rarity.UNCOMMON, mage.cards.s.SpinedFluke.class)); cards.add(new SetCardInfo("Spined Fluke", 160, Rarity.UNCOMMON, mage.cards.s.SpinedFluke.class));
cards.add(new SetCardInfo("Spire Owl", 98, Rarity.COMMON, mage.cards.s.SpireOwl.class)); cards.add(new SetCardInfo("Spire Owl", 98, Rarity.COMMON, mage.cards.s.SpireOwl.class));
cards.add(new SetCardInfo("Sporogenesis", 273, Rarity.RARE, mage.cards.s.Sporogenesis.class)); cards.add(new SetCardInfo("Sporogenesis", 273, Rarity.RARE, mage.cards.s.Sporogenesis.class));

View file

@ -219,9 +219,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
} else { } else {
MageObject mageObject = game.getObject(this.sourceId); MageObject mageObject = game.getObject(this.sourceId);
if (mageObject instanceof Emblem) { if (mageObject instanceof Emblem) {
return ((Emblem) mageObject).getControllerId().equals(playerId); return ((Emblem) mageObject).isControlledBy(playerId);
} else if (mageObject instanceof Plane) { } else if (mageObject instanceof Plane) {
return ((Plane) mageObject).getControllerId().equals(playerId); return ((Plane) mageObject).isControlledBy(playerId);
} else if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) { } else if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) {
return ((Card) mageObject).isOwnedBy(playerId); return ((Card) mageObject).isOwnedBy(playerId);
} }

View file

@ -0,0 +1,50 @@
/*
* 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.permanent.Permanent;
/**
*
* @author jeffwadsworth
*/
public class ControllerPlaysLandTriggeredAbility extends TriggeredAbilityImpl {
public ControllerPlaysLandTriggeredAbility(Zone zone, Effect effect, Boolean optional) {
super(zone, effect, optional);
}
public ControllerPlaysLandTriggeredAbility(ControllerPlaysLandTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.LAND_PLAYED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent land = game.getPermanent(event.getTargetId());
return land.getControllerId().equals(controllerId);
}
@Override
public ControllerPlaysLandTriggeredAbility copy() {
return new ControllerPlaysLandTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever you play a land, ";
}
}

View file

@ -0,0 +1,49 @@
/*
* 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.permanent.Permanent;
/**
*
* @author jeffwadsworth
*/
public class OpponentPlaysLandTriggeredAbility extends TriggeredAbilityImpl {
public OpponentPlaysLandTriggeredAbility(Zone zone, Effect effect, Boolean optional) {
super(zone, effect, optional);
}
public OpponentPlaysLandTriggeredAbility(OpponentPlaysLandTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LAND_PLAYED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent land = game.getPermanent(event.getTargetId());
return game.getOpponents(controllerId).contains(land.getControllerId());
}
@Override
public OpponentPlaysLandTriggeredAbility copy() {
return new OpponentPlaysLandTriggeredAbility(this);
}
@Override
public String getRule() {
return "Whenever an opponent plays a land, ";
}
}

View file

@ -0,0 +1,79 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common.continuous;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author jeffwadsworth
*/
public class BecomesEnchantmentSourceEffect extends ContinuousEffectImpl implements SourceEffect {
public BecomesEnchantmentSourceEffect() {
super(Duration.Custom, Outcome.AddAbility);
staticText = "{this} becomes an Enchantment";
dependencyTypes.add(DependencyType.EnchantmentAddingRemoving);
}
public BecomesEnchantmentSourceEffect(final BecomesEnchantmentSourceEffect effect) {
super(effect);
}
@Override
public BecomesEnchantmentSourceEffect copy() {
return new BecomesEnchantmentSourceEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
affectedObjectList.add(new MageObjectReference(source.getSourceId(), game));
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = affectedObjectList.get(0).getPermanent(game);
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getCardType().clear();
permanent.getSubtype(game).clear();
if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) {
permanent.getCardType().add(CardType.ENCHANTMENT);
}
}
break;
}
return true;
}
this.discard();
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return Layer.TypeChangingEffects_4 == layer;
}
}

View file

@ -12,6 +12,9 @@ public interface Controllable {
UUID getId(); UUID getId();
default boolean isControlledBy(UUID controllerID){ default boolean isControlledBy(UUID controllerID){
if(getControllerId() == null){
return false;
}
return getControllerId().equals(controllerID); return getControllerId().equals(controllerID);
} }
} }

View file

@ -2600,7 +2600,7 @@ public abstract class GameImpl implements Game, Serializable {
boolean addPlaneAgain = false; boolean addPlaneAgain = false;
for (Iterator<CommandObject> it = this.getState().getCommand().iterator(); it.hasNext();) { for (Iterator<CommandObject> it = this.getState().getCommand().iterator(); it.hasNext();) {
CommandObject obj = it.next(); CommandObject obj = it.next();
if (obj.getControllerId().equals(playerId)) { if (obj.isControlledBy(playerId)) {
if (obj instanceof Emblem) { if (obj instanceof Emblem) {
((Emblem) obj).discardEffects();// This may not be the best fix but it works ((Emblem) obj).discardEffects();// This may not be the best fix but it works
} }

View file

@ -3,17 +3,16 @@ package mage.game.command;
import java.util.UUID; import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.game.Controllable;
/** /**
* *
* @author Viserion, nantuko * @author Viserion, nantuko
*/ */
public interface CommandObject extends MageObject { public interface CommandObject extends MageObject, Controllable {
UUID getSourceId(); UUID getSourceId();
UUID getControllerId();
void assignNewId(); void assignNewId();
MageObject getSourceObject(); MageObject getSourceObject();