diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index 3bc9f70e81c..80ce4867c59 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -144,7 +144,7 @@ public class GameView implements Serializable { stack.put(stackObject.getId(), new CardView(((StackAbility) stackObject))); checkPaid(stackObject.getId(), ((StackAbility) stackObject)); } else { - logger.fatal("Object can't be cast to StackAbility: " + object.getName() + " " + object.toString()); + logger.fatal("Object can't be cast to StackAbility: " + object.getName() + " " + object.toString() + " " + object.getClass().toString()); } } } else { diff --git a/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java b/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java index 7709f8614fb..f6550ca84e3 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java @@ -27,21 +27,24 @@ */ package mage.sets.avacynrestored; -import mage.constants.*; +import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; -import mage.cards.CardsImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.players.Library; import mage.players.Player; import mage.target.common.TargetOpponent; - -import java.util.UUID; -import mage.MageObject; -import mage.abilities.effects.ContinuousEffect; import mage.target.targetpointer.FixedTarget; /** @@ -54,7 +57,6 @@ public class StolenGoods extends CardImpl { super(ownerId, 78, "Stolen Goods", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{U}"); this.expansionSetCode = "AVR"; - // Target opponent exiles cards from the top of his or her library until he or she exiles a nonland card. Until end of turn, you may cast that card without paying its mana cost. this.getSpellAbility().addEffect(new StolenGoodsEffect()); this.getSpellAbility().addTarget(new TargetOpponent()); @@ -96,14 +98,13 @@ class StolenGoodsEffect extends OneShotEffect { do { card = library.removeFromTop(game); if (card != null) { - opponent.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + opponent.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName()); } } while (library.size() > 0 && card != null && card.getCardType().contains(CardType.LAND)); if (card != null) { - opponent.revealCards("Card to cast", new CardsImpl(card), game); ContinuousEffect effect = new StolenGoodsCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); + effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); game.addEffect(effect, source); } return true; @@ -135,7 +136,8 @@ class StolenGoodsCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (getTargetPointer().getFirst(game, source).equals(sourceId) && affectedControllerId.equals(source.getControllerId())) { + if (sourceId != null && sourceId.equals(getTargetPointer().getFirst(game, source)) + && affectedControllerId.equals(source.getControllerId())) { Card card = game.getCard(sourceId); if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) { Player player = game.getPlayer(affectedControllerId); diff --git a/Mage.Sets/src/mage/sets/exodus/SurvivalOfTheFittest.java b/Mage.Sets/src/mage/sets/exodus/SurvivalOfTheFittest.java index 02f9e2d5055..36a1fe03ce0 100644 --- a/Mage.Sets/src/mage/sets/exodus/SurvivalOfTheFittest.java +++ b/Mage.Sets/src/mage/sets/exodus/SurvivalOfTheFittest.java @@ -28,16 +28,15 @@ package mage.sets.exodus; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.costs.mana.ColoredManaCost; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -49,9 +48,9 @@ import mage.target.common.TargetCardInLibrary; * @author jeffwadsworth */ public class SurvivalOfTheFittest extends CardImpl { - + private static final FilterCard filter = new FilterCard("creature card"); - + static { filter.add(new CardTypePredicate(CardType.CREATURE)); } @@ -60,7 +59,6 @@ public class SurvivalOfTheFittest extends CardImpl { super(ownerId, 129, "Survival of the Fittest", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); this.expansionSetCode = "EXO"; - // {G}, Discard a creature card: Search your library for a creature card, reveal that card, and put it into your hand. Then shuffle your library. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true), new ColoredManaCost(ColoredManaSymbol.G)); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SarkhanTheMad.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SarkhanTheMad.java index 9124f195994..8cdd3585f79 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SarkhanTheMad.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SarkhanTheMad.java @@ -29,11 +29,8 @@ package mage.sets.riseoftheeldrazi; import java.util.List; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.EntersBattlefieldAbility; @@ -41,8 +38,11 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.Card; import mage.cards.CardImpl; -import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -67,7 +67,6 @@ public class SarkhanTheMad extends CardImpl { this.subtype.add("Sarkhan"); this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(7)), false)); - this.addAbility(new LoyaltyAbility(new SarkhanTheMadRevealAndDrawEffect(), 0)); Target targetCreature = new TargetCreaturePermanent(); @@ -94,29 +93,28 @@ class SarkhanTheMadRevealAndDrawEffect extends OneShotEffect { private static final String effectText = "Reveal the top card of your library and put it into your hand. {this} deals damage to himself equal to that card's converted mana cost"; - SarkhanTheMadRevealAndDrawEffect ( ) { + SarkhanTheMadRevealAndDrawEffect() { super(Outcome.DrawCard); staticText = effectText; } - SarkhanTheMadRevealAndDrawEffect ( SarkhanTheMadRevealAndDrawEffect effect ) { + SarkhanTheMadRevealAndDrawEffect(SarkhanTheMadRevealAndDrawEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null && player.getLibrary().size() > 0) { - Card card = player.getLibrary().removeFromTop(game); - Permanent permanent = game.getPermanent(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + Card card = controller.getLibrary().getFromTop(game); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (card != null) { - card.moveToZone(Zone.HAND, source.getSourceId(), game, false); - permanent.damage(card.getManaCost().convertedManaCost(), this.getId(), game, false, false); - Cards cards = new CardsImpl(); - cards.add(card); - player.revealCards("Sarkhan the Mad", cards, game); - return true; + controller.moveCards(card, null, Zone.HAND, source, game); + sourcePermanent.damage(card.getManaCost().convertedManaCost(), source.getSourceId(), game, false, false); + controller.revealCards(sourceObject.getIdName(), new CardsImpl(card), game); } + return true; } return false; } @@ -132,19 +130,19 @@ class SarkhanTheMadSacEffect extends OneShotEffect { private static final String effectText = "Target creature's controller sacrifices it, then that player puts a 5/5 red Dragon creature token with flying onto the battlefield"; - SarkhanTheMadSacEffect ( ) { + SarkhanTheMadSacEffect() { super(Outcome.Sacrifice); staticText = effectText; } - SarkhanTheMadSacEffect ( SarkhanTheMadSacEffect effect ) { + SarkhanTheMadSacEffect(SarkhanTheMadSacEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget()); - if ( permanent != null ) { + if (permanent != null) { Player player = game.getPlayer(permanent.getControllerId()); permanent.sacrifice(this.getId(), game); Token dragonToken = new DragonToken(); @@ -171,12 +169,12 @@ class SarkhanTheMadDragonDamageEffect extends OneShotEffect { filter.add(new SubtypePredicate("Dragon")); } - SarkhanTheMadDragonDamageEffect ( ) { + SarkhanTheMadDragonDamageEffect() { super(Outcome.Damage); staticText = effectText; } - SarkhanTheMadDragonDamageEffect ( SarkhanTheMadDragonDamageEffect effect ) { + SarkhanTheMadDragonDamageEffect(SarkhanTheMadDragonDamageEffect effect) { super(effect); } @@ -184,8 +182,8 @@ class SarkhanTheMadDragonDamageEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { List dragons = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); Player player = game.getPlayer(source.getTargets().getFirstTarget()); - if ( player != null && dragons != null && !dragons.isEmpty() ) { - for ( Permanent dragon : dragons ) { + if (player != null && dragons != null && !dragons.isEmpty()) { + for (Permanent dragon : dragons) { player.damage(dragon.getPower().getValue(), dragon.getId(), game, true, false); } return true; @@ -202,7 +200,8 @@ class SarkhanTheMadDragonDamageEffect extends OneShotEffect { } class DragonToken extends mage.game.permanent.token.DragonToken { - DragonToken ( ) { + + DragonToken() { super(); this.power = new MageInt(5); this.toughness = new MageInt(5); diff --git a/Mage/src/mage/MageObjectReference.java b/Mage/src/mage/MageObjectReference.java index 8242aff19ad..85edcc3c625 100644 --- a/Mage/src/mage/MageObjectReference.java +++ b/Mage/src/mage/MageObjectReference.java @@ -25,24 +25,27 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage; import java.io.Serializable; import java.util.UUID; import mage.cards.Card; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import org.apache.log4j.Logger; /** * A object reference that takes zone changes into account. * * @author LevelX2 */ - public class MageObjectReference implements Comparable, Serializable { + private static final transient Logger logger = Logger.getLogger(MageObjectReference.class); + private final UUID sourceId; private final int zoneChangeCounter; @@ -50,20 +53,21 @@ public class MageObjectReference implements Comparable, Ser this.sourceId = mageObject.getId(); this.zoneChangeCounter = mageObject.getZoneChangeCounter(game); } + /** - * That values manually (can be used to let it reference to a Permanent - * that is not yet on the battlefield. - * + * That values manually (can be used to let it reference to a Permanent that + * is not yet on the battlefield. + * * @param sourceId * @param zoneChangeCounter - * @param game + * @param game */ public MageObjectReference(UUID sourceId, int zoneChangeCounter, Game game) { this.sourceId = sourceId; this.zoneChangeCounter = zoneChangeCounter; } - public MageObjectReference(UUID sourceId, Game game) { + public MageObjectReference(UUID sourceId, Game game) { this.sourceId = sourceId; MageObject mageObject = game.getObject(sourceId); if (mageObject != null) { @@ -72,7 +76,18 @@ public class MageObjectReference implements Comparable, Ser if (game.getPlayerList().contains(sourceId)) { this.zoneChangeCounter = 0; } else { - throw new IllegalArgumentException("The provided sourceId is not connected to an object in the game"); + logger.error("The provided sourceId is not connected to an object in the game id:" + sourceId); + for (StackObject stackObject : game.getStack()) { + logger.error("StackObject: " + stackObject.getId() + " sourceId" + stackObject.getSourceId() + " name" + stackObject.getName()); + } + mageObject = game.getLastKnownInformation(sourceId, Zone.STACK); + if (mageObject != null) { + this.zoneChangeCounter = mageObject.getZoneChangeCounter(game); + logger.error("SourceId found in LKI"); + } else { + logger.error("SourceId NOT found in LKI"); + this.zoneChangeCounter = 0; + } } } } @@ -96,8 +111,8 @@ public class MageObjectReference implements Comparable, Ser @Override public boolean equals(Object v) { if (v instanceof MageObjectReference) { - if (((MageObjectReference)v).getSourceId().equals(this.sourceId)) { - return ((MageObjectReference)v).getZoneChangeCounter() == this.zoneChangeCounter; + if (((MageObjectReference) v).getSourceId().equals(this.sourceId)) { + return ((MageObjectReference) v).getZoneChangeCounter() == this.zoneChangeCounter; } } return false; @@ -117,7 +132,7 @@ public class MageObjectReference implements Comparable, Ser public boolean refersTo(MageObject mageObject, Game game) { if (mageObject != null) { if (mageObject instanceof Spell) { - return ((Spell)mageObject).getSourceId().equals(sourceId) && this.zoneChangeCounter == mageObject.getZoneChangeCounter(game); + return ((Spell) mageObject).getSourceId().equals(sourceId) && this.zoneChangeCounter == mageObject.getZoneChangeCounter(game); } return mageObject.getId().equals(sourceId) && this.zoneChangeCounter == mageObject.getZoneChangeCounter(game); } diff --git a/Mage/src/mage/cards/repository/CardRepository.java b/Mage/src/mage/cards/repository/CardRepository.java index f7a2478a817..6cd148fbe91 100644 --- a/Mage/src/mage/cards/repository/CardRepository.java +++ b/Mage/src/mage/cards/repository/CardRepository.java @@ -63,7 +63,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 41; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 35; + private static final long CARD_CONTENT_VERSION = 36; private final Random random = new Random(); private Dao cardDao; diff --git a/Mage/src/mage/watchers/common/LandfallWatcher.java b/Mage/src/mage/watchers/common/LandfallWatcher.java index 2b4df7a7a12..d4d14ba0bb1 100644 --- a/Mage/src/mage/watchers/common/LandfallWatcher.java +++ b/Mage/src/mage/watchers/common/LandfallWatcher.java @@ -35,8 +35,8 @@ public class LandfallWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.getCardType().contains(CardType.LAND) && !playerPlayedLand.contains(event.getPlayerId())) { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent != null && permanent.getCardType().contains(CardType.LAND) && !playerPlayedLand.contains(event.getPlayerId())) { playerPlayedLand.add(event.getPlayerId()); } }