Merge origin/master

This commit is contained in:
fireshoes 2015-02-03 00:49:28 -06:00
commit 7f5bb1ba01
18 changed files with 188 additions and 110 deletions

View file

@ -30,6 +30,7 @@ package mage.abilities.common;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.SpecialAction;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.effects.OneShotEffect;
@ -46,10 +47,12 @@ import mage.players.Player;
* @author LevelX2
*/
public class TurnFaceUpAbility extends ActivatedAbilityImpl {
public class TurnFaceUpAbility extends SpecialAction {
public TurnFaceUpAbility(Costs<Cost> costs) {
super(Zone.BATTLEFIELD, new TurnFaceUpEffect(), costs);
super(Zone.BATTLEFIELD);
this.addEffect(new TurnFaceUpEffect());
this.addCost(costs);
this.usesStack = false;
this.abilityType = AbilityType.SPECIAL_ACTION;
this.setRuleVisible(false); // will be made visible only to controller in CardView

View file

@ -152,7 +152,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
PermanentCard permanent = new PermanentCard(card, card.getOwnerId());
game.getBattlefield().addPermanent(permanent);
game.setZone(card.getId(), Zone.BATTLEFIELD);
card.setZone(Zone.BATTLEFIELD, game);
game.applyEffects();
permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
game.applyEffects();

View file

@ -168,7 +168,6 @@ class BestowTypeChangingEffect extends ContinuousEffectImpl implements SourceEff
permanent.getCardType().remove(CardType.CREATURE);
permanent.getSubtype().clear();
if (!permanent.getSubtype().contains("Aura")) {
permanent.getSubtype().add("Aura");
}
}

View file

@ -1,5 +1,6 @@
package mage.abilities.keyword;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.DiesTriggeredAbility;
@ -13,6 +14,7 @@ import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import org.apache.log4j.Logger;
/**
* @author Loki
@ -38,6 +40,7 @@ public class UndyingAbility extends DiesTriggeredAbility {
if (super.checkTrigger(event, game)) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (!permanent.getCounters().containsKey(CounterType.P1P1) || permanent.getCounters().getCount(CounterType.P1P1) == 0) {
Logger.getLogger(UndyingAbility.class).info("Undying trigger: " + getSourceId());
game.getState().setValue("undying" + getSourceId(),permanent.getId());
return true;
}
@ -95,6 +98,7 @@ class UndyingReplacementEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) {
game.getState().setValue("undying" + source.getSourceId(), null);
permanent.addCounters(CounterType.P1P1.createInstance(), game);
}
used = true;
@ -110,9 +114,10 @@ class UndyingReplacementEffect extends ReplacementEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getTargetId().equals(source.getSourceId())) {
// Check if undying condition is true
UUID target = (UUID) game.getState().getValue("undying" + source.getSourceId());
if (target.equals(source.getSourceId())) {
game.getState().setValue("undying" + source.getSourceId(), null);
UUID targetId = (UUID) game.getState().getValue("undying" + source.getSourceId());
Logger.getLogger(UndyingReplacementEffect.class).info("Undying replacement applies: " + targetId + " eventSourceId " + event.getTargetId());
if (targetId != null && targetId.equals(source.getSourceId())) {
return true;
}
}

View file

@ -53,6 +53,7 @@ public interface Card extends MageObject {
void setOwnerId(UUID ownerId);
void addAbility(Ability ability);
void addWatcher(Watcher watcher);
void setSpellAbility(SpellAbility ability);
SpellAbility getSpellAbility();
List<String> getRules();
List<Watcher> getWatchers();
@ -140,4 +141,12 @@ public interface Card extends MageObject {
@Override
Card copy();
/**
*
* @return The main card of a split half card, otherwise thae card itself is returned
*/
Card getMainCard();
void setZone(Zone zone, Game game);
}

View file

@ -258,7 +258,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
public SpellAbility getSpellAbility() {
if (spellAbility == null) {
for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) {
if (ability instanceof SpellAbility) {
// name check prevents that alternate casting methods (like "cast [card name] using bestow") are returned here
if (ability instanceof SpellAbility && ability.toString().endsWith(getName())) {
spellAbility = (SpellAbility) ability;
}
}
@ -419,38 +420,39 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
@Override
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ability.getId(), controllerId, fromZone, Zone.STACK);
Card mainCard = getMainCard();
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
if (!game.replaceEvent(event)) {
if (event.getFromZone() != null) {
switch (event.getFromZone()) {
case GRAVEYARD:
game.getPlayer(ownerId).removeFromGraveyard(this, game);
game.getPlayer(ownerId).removeFromGraveyard(mainCard, game);
break;
case HAND:
game.getPlayer(ownerId).removeFromHand(this, game);
game.getPlayer(ownerId).removeFromHand(mainCard, game);
break;
case LIBRARY:
game.getPlayer(ownerId).removeFromLibrary(this, game);
game.getPlayer(ownerId).removeFromLibrary(mainCard, game);
break;
case EXILED:
game.getExile().removeCard(this, game);
game.getExile().removeCard(mainCard, game);
break;
case OUTSIDE:
game.getPlayer(ownerId).getSideboard().remove(this);
game.getPlayer(ownerId).getSideboard().remove(mainCard);
break;
case COMMAND:
game.getState().getCommand().remove((Commander)game.getObject(objectId));
game.getState().getCommand().remove((Commander)game.getObject(mainCard.getId()));
break;
default:
//logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone());
}
game.rememberLKI(objectId, event.getFromZone(), this);
game.rememberLKI(mainCard.getId(), event.getFromZone(), this);
}
game.getStack().push(new Spell(this, ability.copy(), controllerId, event.getFromZone()));
game.setZone(objectId, event.getToZone());
setZone(event.getToZone(), game);
game.fireEvent(event);
return game.getState().getZone(objectId) == Zone.STACK;
return game.getState().getZone(mainCard.getId()) == Zone.STACK;
}
return false;
}
@ -557,7 +559,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
// make sure the controller of all continuous effects of this card are switched to the current controller
game.getContinuousEffects().setController(objectId, event.getPlayerId());
game.addPermanent(permanent);
game.setZone(objectId, Zone.BATTLEFIELD);
setZone(Zone.BATTLEFIELD, game);
game.setScopeRelevant(true);
permanent.setTapped(tapped);
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
@ -777,4 +779,20 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
}
return name;
}
@Override
public Card getMainCard() {
return this;
}
@Override
public void setZone(Zone zone, Game game) {
game.setZone(getId(), zone);
}
@Override
public void setSpellAbility(SpellAbility ability) {
spellAbility = ability;
}
}

View file

@ -31,15 +31,16 @@ package mage.cards;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.SpellAbilityType;
import static mage.constants.SpellAbilityType.SPLIT_LEFT;
import static mage.constants.SpellAbilityType.SPLIT_RIGHT;
import mage.constants.Zone;
import mage.game.Game;
import mage.watchers.Watcher;
@ -90,7 +91,28 @@ public abstract class SplitCard extends CardImpl {
public Card getRightHalfCard () {
return rightHalfCard;
}
@Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) {
game.getState().setZone(getLeftHalfCard().getId(), toZone);
game.getState().setZone(getRightHalfCard().getId(), toZone);
return true;
}
return false;
}
@Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) {
Zone currentZone = game.getState().getZone(getId());
game.getState().setZone(getLeftHalfCard().getId(), currentZone);
game.getState().setZone(getRightHalfCard().getId(), currentZone);
return true;
}
return false;
}
@Override
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
switch(ability.getSpellAbilityType()) {
@ -103,6 +125,14 @@ public abstract class SplitCard extends CardImpl {
}
}
@Override
public void setZone(Zone zone, Game game) {
super.setZone(zone, game);
game.setZone(getLeftHalfCard().getId(), zone);
game.setZone(getRightHalfCard().getId(), zone);
}
@Override
public Abilities<Ability> getAbilities(){
Abilities<Ability> allAbilites = new AbilitiesImpl<>();
@ -198,7 +228,21 @@ class LeftHalfCard extends CardImpl {
@Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
}
}
@Override
public Card getMainCard() {
return splitCardParent;
}
@Override
public void setZone(Zone zone, Game game) {
super.setZone(zone, game);
game.setZone(splitCardParent.getId(), zone);
game.setZone(splitCardParent.getRightHalfCard().getId(), zone);
}
}
/*
@ -247,4 +291,17 @@ class RightHalfCard extends CardImpl {
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
}
@Override
public Card getMainCard() {
return splitCardParent;
}
@Override
public void setZone(Zone zone, Game game) {
super.setZone(zone, game);
game.setZone(splitCardParent.getId(), zone);
game.setZone(splitCardParent.getLeftHalfCard().getId(), zone);
}
}

View file

@ -2328,19 +2328,18 @@ public abstract class GameImpl implements Game, Serializable {
loadCards(ownerId, graveyard);
for (Card card : library) {
setZone(card.getId(), Zone.LIBRARY);
player.getLibrary().putOnTop(card, this);
}
for (Card card : hand) {
setZone(card.getId(), Zone.HAND);
card.setZone(Zone.HAND, this);
player.getHand().add(card);
}
for (Card card : graveyard) {
setZone(card.getId(), Zone.GRAVEYARD);
card.setZone(Zone.GRAVEYARD, this);
player.getGraveyard().add(card);
}
for (PermanentCard card : battlefield) {
setZone(card.getId(), Zone.BATTLEFIELD);
card.setZone(Zone.BATTLEFIELD, this);
card.setOwnerId(ownerId);
PermanentCard permanent = new PermanentCard(card.getCard(), ownerId);
getBattlefield().addPermanent(permanent);

View file

@ -210,7 +210,7 @@ public class Spell implements StackObject, Card {
}
}
}
if (game.getState().getZone(card.getId()) == Zone.STACK) {
if (game.getState().getZone(card.getMainCard().getId()) == Zone.STACK) {
card.moveToZone(Zone.GRAVEYARD, ability.getSourceId(), game, false);
}
}
@ -235,7 +235,8 @@ public class Spell implements StackObject, Card {
// TODO: Find a better way to prevent bestow creatures from being effected by creature affecting abilities
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null && permanent instanceof PermanentCard) {
((PermanentCard) permanent).getCard().getCardType().add(CardType.CREATURE);
permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set
((PermanentCard) permanent).getCard().getCardType().add(CardType.CREATURE);
}
card.getCardType().add(CardType.CREATURE);
}
@ -999,4 +1000,19 @@ public class Spell implements StackObject, Card {
return card.isMorphCard();
}
@Override
public Card getMainCard() {
return card.getMainCard();
}
@Override
public void setZone(Zone zone, Game game) {
card.setZone(zone, game);
}
@Override
public void setSpellAbility(SpellAbility ability) {
throw new UnsupportedOperationException("Not supported.");
}
}

View file

@ -131,7 +131,7 @@ public class Library implements Serializable {
public void putOnTop(Card card, Game game) {
if (card.getOwnerId().equals(playerId)) {
game.setZone(card.getId(), Zone.LIBRARY);
card.setZone(Zone.LIBRARY, game);
library.addFirst(card.getId());
}
else {
@ -141,7 +141,7 @@ public class Library implements Serializable {
public void putOnBottom(Card card, Game game) {
if (card.getOwnerId().equals(playerId)) {
game.setZone(card.getId(), Zone.LIBRARY);
card.setZone(Zone.LIBRARY, game);
if (library.contains(card.getId())) {
library.remove(card.getId());
}
@ -226,7 +226,7 @@ public class Library implements Serializable {
public void addAll(Set<Card> cards, Game game) {
for (Card card: cards) {
game.setZone(card.getId(), Zone.LIBRARY);
card.setZone(Zone.LIBRARY, game);
library.add(card.getId());
}
}

View file

@ -650,8 +650,8 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean putInHand(Card card, Game game) {
if (card.getOwnerId().equals(playerId)) {
card.setZone(Zone.HAND, game);
this.hand.add(card);
game.setZone(card.getId(), Zone.HAND);
} else {
return game.getPlayer(card.getOwnerId()).putInHand(card, game);
}
@ -924,7 +924,7 @@ public abstract class PlayerImpl implements Player, Serializable {
if (card != null) {
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability.getSourceId(), playerId))) {
int bookmark = game.bookmarkState();
Zone fromZone = game.getState().getZone(card.getId());
Zone fromZone = game.getState().getZone(card.getMainCard().getId());
card.cast(game, fromZone, ability, playerId);
Spell spell = game.getStack().getSpell(ability.getId());
// some effects set sourceId to cast without paying mana costs