mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 21:12:04 -08:00
Merge remote-tracking branch 'upstream/master' into CMH-GuiltyConscienceAndBackfire
This commit is contained in:
commit
d1c8796a49
7431 changed files with 56515 additions and 21681 deletions
|
|
@ -1,19 +1,22 @@
|
|||
package mage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.keyword.ChangelingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.FrameStyle;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface MageObject extends MageItem, Serializable {
|
||||
|
||||
String getName();
|
||||
|
|
@ -32,16 +35,16 @@ public interface MageObject extends MageItem, Serializable {
|
|||
|
||||
boolean hasSubtype(String subtype, Game game);
|
||||
|
||||
List<String> getSupertype();
|
||||
EnumSet<SuperType> getSuperType();
|
||||
|
||||
Abilities<Ability> getAbilities();
|
||||
|
||||
boolean hasAbility(UUID abilityId, Game game);
|
||||
|
||||
ObjectColor getColor(Game game);
|
||||
|
||||
|
||||
ObjectColor getFrameColor(Game game);
|
||||
|
||||
|
||||
FrameStyle getFrameStyle();
|
||||
|
||||
ManaCosts<ManaCost> getManaCost();
|
||||
|
|
@ -51,10 +54,9 @@ public interface MageObject extends MageItem, Serializable {
|
|||
MageInt getPower();
|
||||
|
||||
MageInt getToughness();
|
||||
|
||||
|
||||
int getStartingLoyalty();
|
||||
|
||||
|
||||
|
||||
|
||||
void adjustCosts(Ability ability, Game game);
|
||||
|
||||
|
|
@ -83,33 +85,108 @@ public interface MageObject extends MageItem, Serializable {
|
|||
void setZoneChangeCounter(int value, Game game);
|
||||
|
||||
|
||||
|
||||
default boolean isCreature(){
|
||||
default boolean isCreature() {
|
||||
return getCardType().contains(CardType.CREATURE);
|
||||
}
|
||||
|
||||
default boolean isArtifact(){
|
||||
default boolean isArtifact() {
|
||||
return getCardType().contains(CardType.ARTIFACT);
|
||||
}
|
||||
|
||||
default boolean isLand(){
|
||||
default boolean isLand() {
|
||||
return getCardType().contains(CardType.LAND);
|
||||
}
|
||||
|
||||
default boolean isEnchantment(){
|
||||
default boolean isEnchantment() {
|
||||
return getCardType().contains(CardType.ENCHANTMENT);
|
||||
}
|
||||
|
||||
default boolean isInstant(){
|
||||
default boolean isInstant() {
|
||||
return getCardType().contains(CardType.INSTANT);
|
||||
}
|
||||
|
||||
default boolean isSorcery(){
|
||||
default boolean isSorcery() {
|
||||
return getCardType().contains(CardType.SORCERY);
|
||||
}
|
||||
|
||||
default boolean isPlaneswalker(){
|
||||
default boolean isPlaneswalker() {
|
||||
return getCardType().contains(CardType.PLANESWALKER);
|
||||
}
|
||||
|
||||
default boolean isPermanent() {
|
||||
return isCreature() || isArtifact() || isPlaneswalker() || isEnchantment() || isLand();
|
||||
}
|
||||
|
||||
default boolean isLegendary() {
|
||||
return getSuperType().contains(SuperType.LEGENDARY);
|
||||
}
|
||||
|
||||
default boolean isSnow() {
|
||||
return getSuperType().contains(SuperType.SNOW);
|
||||
}
|
||||
|
||||
default void addSuperType(SuperType superType) {
|
||||
getSuperType().add(superType);
|
||||
}
|
||||
|
||||
default boolean isBasic() {
|
||||
return getSuperType().contains(SuperType.BASIC);
|
||||
}
|
||||
|
||||
default boolean isWorld() {
|
||||
return getSuperType().contains(SuperType.WORLD);
|
||||
}
|
||||
|
||||
default void addCardType(CardType cardType) {
|
||||
getCardType().add(cardType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two cards share card types.
|
||||
*
|
||||
* @param otherCard
|
||||
* @return
|
||||
*/
|
||||
default boolean shareTypes(Card otherCard) {
|
||||
|
||||
if (otherCard == null) {
|
||||
throw new IllegalArgumentException("Params can't be null");
|
||||
}
|
||||
|
||||
for (CardType type : getCardType()) {
|
||||
if (otherCard.getCardType().contains(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
default boolean shareSubtypes(Card otherCard, Game game) {
|
||||
|
||||
if (otherCard == null) {
|
||||
throw new IllegalArgumentException("Params can't be null");
|
||||
}
|
||||
|
||||
if (this.isCreature() && otherCard.isCreature()) {
|
||||
if (this.getAbilities().contains(ChangelingAbility.getInstance())
|
||||
|| this.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)
|
||||
|| otherCard.getAbilities().contains(ChangelingAbility.getInstance())
|
||||
|| otherCard.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (String subtype : this.getSubtype(game)) {
|
||||
if (otherCard.getSubtype(game).contains(subtype)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
default void addCardTypes(EnumSet<CardType> cardType){
|
||||
getCardType().addAll(cardType);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import mage.abilities.keyword.ChangelingAbility;
|
|||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.cards.FrameStyle;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.CardUtil;
|
||||
|
|
@ -56,7 +57,7 @@ public abstract class MageObjectImpl implements MageObject {
|
|||
protected FrameStyle frameStyle;
|
||||
protected EnumSet<CardType> cardType = EnumSet.noneOf(CardType.class);
|
||||
protected List<String> subtype = new ArrayList<>();
|
||||
protected List<String> supertype = new ArrayList<>();
|
||||
protected EnumSet<SuperType> supertype = EnumSet.noneOf(SuperType.class);
|
||||
protected Abilities<Ability> abilities;
|
||||
protected String text;
|
||||
protected MageInt power;
|
||||
|
|
@ -91,7 +92,7 @@ public abstract class MageObjectImpl implements MageObject {
|
|||
abilities = object.abilities.copy();
|
||||
this.cardType.addAll(object.cardType);
|
||||
this.subtype.addAll(object.subtype);
|
||||
this.supertype.addAll(object.supertype);
|
||||
supertype.addAll(object.supertype);
|
||||
this.copy = object.copy;
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +137,7 @@ public abstract class MageObjectImpl implements MageObject {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSupertype() {
|
||||
public EnumSet<SuperType> getSuperType() {
|
||||
return supertype;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ package mage.abilities;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
|
|
@ -245,7 +246,7 @@ public interface Abilities<T extends Ability> extends List<T>, Serializable {
|
|||
* @param abilityId
|
||||
* @return
|
||||
*/
|
||||
T get(UUID abilityId);
|
||||
Optional<T> get(UUID abilityId);
|
||||
|
||||
/**
|
||||
* TODO The usage of this method seems redundant to that of
|
||||
|
|
|
|||
|
|
@ -27,13 +27,6 @@
|
|||
*/
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
|
|
@ -44,6 +37,8 @@ import mage.game.Game;
|
|||
import mage.util.ThreadLocalStringBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @param <T>
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -277,12 +272,7 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
|
||||
@Override
|
||||
public boolean containsRule(T ability) {
|
||||
for (T test : this) {
|
||||
if (ability.getRule().equals(test.getRule())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stream().anyMatch(rule -> rule.getRule().equals(ability.getRule()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -301,32 +291,16 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
|
||||
@Override
|
||||
public boolean containsKey(UUID abilityId) {
|
||||
for (T ability : this) {
|
||||
if (ability.getId().equals(abilityId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stream().anyMatch(ability -> ability.getId().equals(abilityId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsClass(Class classObject) {
|
||||
for (T ability : this) {
|
||||
if (ability.getClass().equals(classObject)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return stream().anyMatch(ability -> ability.getClass().equals(classObject));
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(UUID abilityId) {
|
||||
for (T ability : this) {
|
||||
if (ability.getId().equals(abilityId)) {
|
||||
return ability;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public Optional<T> get(UUID abilityId) {
|
||||
return stream().filter(ability -> ability.getId().equals(abilityId)).findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
*/
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.Mana;
|
||||
|
|
@ -59,11 +63,6 @@ import mage.util.ThreadLocalStringBuilder;
|
|||
import mage.watchers.Watcher;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -287,6 +286,19 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
}
|
||||
|
||||
// 117.6. Some mana costs contain no mana symbols. This represents an unpayable cost. An ability can
|
||||
// also have an unpayable cost if its cost is based on the mana cost of an object with no mana cost.
|
||||
// Attempting to cast a spell or activate an ability that has an unpayable cost is a legal action.
|
||||
// However, attempting to pay an unpayable cost is an illegal action.
|
||||
//
|
||||
// We apply this now, *AFTER* the user has made the choice to pay an alternative cost for the
|
||||
// spell. You can also still cast a spell with an unplayable cost by... not paying it's mana cost.
|
||||
//if (getAbilityType() == AbilityType.SPELL && getManaCostsToPay().isEmpty() && !noMana) {
|
||||
// return false;
|
||||
//}
|
||||
if (getAbilityType() == AbilityType.SPELL && (getManaCostsToPay().isEmpty() && getCosts().isEmpty()) && !noMana) {
|
||||
return false;
|
||||
}
|
||||
// 20121001 - 601.2b
|
||||
// If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
|
||||
// its mana cost; see rule 107.3), the player announces the value of that variable.
|
||||
|
|
@ -328,7 +340,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome();
|
||||
if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game) == false) {
|
||||
if ((variableManaCost != null || announceString != null) && !game.isSimulation()) {
|
||||
game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets with this value of X");
|
||||
game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets");
|
||||
}
|
||||
return false; // when activation of ability is canceled during target selection
|
||||
}
|
||||
|
|
@ -489,7 +501,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
protected String handleOtherXCosts(Game game, Player controller) {
|
||||
StringBuilder announceString = new StringBuilder();
|
||||
for (VariableCost variableCost : this.costs.getVariableCosts()) {
|
||||
if (!(variableCost instanceof VariableManaCost)) {
|
||||
if (!(variableCost instanceof VariableManaCost) && !((Cost) variableCost).isPaid()) {
|
||||
int xValue = variableCost.announceXValue(this, game);
|
||||
Cost fixedCost = variableCost.getFixedCostsFromAnnouncedValue(xValue);
|
||||
if (fixedCost != null) {
|
||||
|
|
@ -506,19 +518,20 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
/**
|
||||
* 601.2b
|
||||
* If a cost that will be paid as the spell is being cast includes Phyrexian mana symbols,
|
||||
* the player announces whether he or she intends to pay 2 life or the corresponding colored mana cost for each of those symbols.
|
||||
* 601.2b If a cost that will be paid as the spell is being cast includes
|
||||
* Phyrexian mana symbols, the player announces whether he or she intends to
|
||||
* pay 2 life or the corresponding colored mana cost for each of those
|
||||
* symbols.
|
||||
*/
|
||||
private void handlePhyrexianManaCosts(Game game, UUID sourceId, Player controller) {
|
||||
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
|
||||
while(costIterator.hasNext()) {
|
||||
while (costIterator.hasNext()) {
|
||||
ManaCost cost = costIterator.next();
|
||||
if(cost instanceof PhyrexianManaCost) {
|
||||
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)cost;
|
||||
if (cost instanceof PhyrexianManaCost) {
|
||||
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost) cost;
|
||||
PayLifeCost payLifeCost = new PayLifeCost(2);
|
||||
if(payLifeCost.canPay(this, sourceId, controller.getId(), game) &&
|
||||
controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + '?', this, game)) {
|
||||
if (payLifeCost.canPay(this, sourceId, controller.getId(), game)
|
||||
&& controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + '?', this, game)) {
|
||||
costIterator.remove();
|
||||
costs.add(payLifeCost);
|
||||
}
|
||||
|
|
@ -558,7 +571,11 @@ public abstract class AbilityImpl implements Ability {
|
|||
} else {
|
||||
String manaSymbol = null;
|
||||
if (variableManaCost.getFilter().isBlack()) {
|
||||
manaSymbol = "B";
|
||||
if (variableManaCost.getFilter().isRed()) {
|
||||
manaSymbol = "B/R";
|
||||
} else {
|
||||
manaSymbol = "B";
|
||||
}
|
||||
} else if (variableManaCost.getFilter().isRed()) {
|
||||
manaSymbol = "R";
|
||||
} else if (variableManaCost.getFilter().isBlue()) {
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
package mage.abilities;
|
||||
|
||||
/**
|
||||
* Created by IGOUDT on 5-3-2017.
|
||||
*/
|
||||
public enum CountType {
|
||||
MORE_THAN, FEWER_THAN, EQUAL_TO;
|
||||
|
||||
|
||||
public static boolean compare(int source, CountType comparison, int target){
|
||||
switch (comparison){
|
||||
case MORE_THAN:
|
||||
return source > target;
|
||||
case FEWER_THAN:
|
||||
return source < target;
|
||||
case EQUAL_TO:
|
||||
return source == target;
|
||||
default:
|
||||
throw new IllegalArgumentException("comparison rules for "+comparison + " missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,20 +28,21 @@
|
|||
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.Iterator;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class DelayedTriggeredAbilities extends AbilitiesImpl<DelayedTriggeredAbility> {
|
||||
public class DelayedTriggeredAbilities extends AbilitiesImpl<DelayedTriggeredAbility> {
|
||||
|
||||
public DelayedTriggeredAbilities() {}
|
||||
public DelayedTriggeredAbilities() {
|
||||
}
|
||||
|
||||
public DelayedTriggeredAbilities(final DelayedTriggeredAbilities abilities) {
|
||||
public DelayedTriggeredAbilities(final DelayedTriggeredAbilities abilities) {
|
||||
super(abilities);
|
||||
}
|
||||
|
||||
|
|
@ -52,9 +53,9 @@ import mage.game.events.GameEvent;
|
|||
|
||||
public void checkTriggers(GameEvent event, Game game) {
|
||||
if (this.size() > 0) {
|
||||
for (Iterator<DelayedTriggeredAbility> it = this.iterator();it.hasNext();) {
|
||||
for (Iterator<DelayedTriggeredAbility> it = this.iterator(); it.hasNext(); ) {
|
||||
DelayedTriggeredAbility ability = it.next();
|
||||
if (ability.getDuration()== Duration.Custom){
|
||||
if (ability.getDuration() == Duration.Custom) {
|
||||
if (ability.isInactive(game)) {
|
||||
it.remove();
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
|
|
@ -44,8 +45,6 @@ import mage.game.Game;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -94,7 +93,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
public boolean canActivate(UUID playerId, Game game) {
|
||||
if (game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|
||||
|| this.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
if (spellAbilityType == SpellAbilityType.SPLIT) {
|
||||
if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
|
||||
return false;
|
||||
}
|
||||
// fix for Gitaxian Probe and casting opponent's spells
|
||||
|
|
@ -110,7 +109,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
}
|
||||
}
|
||||
// Alternate spell abilities (Flashback, Overload) can't be cast with no mana to pay option
|
||||
if (getSpellAbilityType()== SpellAbilityType.BASE_ALTERNATE) {
|
||||
if (getSpellAbilityType() == SpellAbilityType.BASE_ALTERNATE) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && getSourceId().equals(player.getCastSourceIdWithAlternateMana())) {
|
||||
return false;
|
||||
|
|
@ -183,27 +182,27 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
public int getConvertedXManaCost(Card card) {
|
||||
int xMultiplier = 0;
|
||||
int amount = 0;
|
||||
if(card == null) {
|
||||
if (card == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(ManaCost manaCost : card.getManaCost()) {
|
||||
if(manaCost instanceof VariableManaCost) {
|
||||
xMultiplier = ((VariableManaCost)manaCost).getMultiplier();
|
||||
for (ManaCost manaCost : card.getManaCost()) {
|
||||
if (manaCost instanceof VariableManaCost) {
|
||||
xMultiplier = ((VariableManaCost) manaCost).getMultiplier();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasNonManaXCost = false;
|
||||
for(Cost cost : getCosts()) {
|
||||
if(cost instanceof VariableCost) {
|
||||
for (Cost cost : getCosts()) {
|
||||
if (cost instanceof VariableCost) {
|
||||
hasNonManaXCost = true;
|
||||
amount = ((VariableCost) cost).getAmount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!hasNonManaXCost) {
|
||||
if (!hasNonManaXCost) {
|
||||
amount = getManaCostsToPay().getX();
|
||||
}
|
||||
return amount * xMultiplier;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ import mage.game.events.GameEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -126,7 +125,7 @@ class KinshipBaseEffect extends OneShotEffect {
|
|||
if (card != null) {
|
||||
Cards cards = new CardsImpl(card);
|
||||
controller.lookAtCards(sourcePermanent.getName(), cards, game);
|
||||
if (CardUtil.shareSubtypes(sourcePermanent, card, game)) {
|
||||
if (sourcePermanent.shareSubtypes(card, game)) {
|
||||
if (controller.chooseUse(outcome,new StringBuilder("Kinship - Reveal ").append(card.getLogName()).append('?').toString(), source, game)) {
|
||||
controller.revealCards(sourcePermanent.getName(), cards, game);
|
||||
for (Effect effect: kinshipEffects) {
|
||||
|
|
|
|||
|
|
@ -46,14 +46,14 @@ import mage.constants.Zone;
|
|||
public class LieutenantAbility extends SimpleStaticAbility {
|
||||
|
||||
public LieutenantAbility(ContinuousEffect effect) {
|
||||
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.getInstance(), "<i>Lieutenant</i> - As long as you control your commander, {this} gets +2/+2"));
|
||||
this.addEffect(new ConditionalContinuousEffect(effect, CommanderInPlayCondition.getInstance(), effect.getText(null)));
|
||||
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.instance, "<i>Lieutenant</i> - As long as you control your commander, {this} gets +2/+2"));
|
||||
this.addEffect(new ConditionalContinuousEffect(effect, CommanderInPlayCondition.instance, effect.getText(null)));
|
||||
}
|
||||
|
||||
public LieutenantAbility(Effects effects) {
|
||||
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.getInstance(), "<i>Lieutenant</i> - As long as you control your commander, {this} gets +2/+2"));
|
||||
super(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), CommanderInPlayCondition.instance, "<i>Lieutenant</i> - As long as you control your commander, {this} gets +2/+2"));
|
||||
for (Effect effect : effects) {
|
||||
this.addEffect(new ConditionalContinuousEffect((ContinuousEffect) effect, CommanderInPlayCondition.getInstance(), effect.getText(null)));
|
||||
this.addEffect(new ConditionalContinuousEffect((ContinuousEffect) effect, CommanderInPlayCondition.instance, effect.getText(null)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
|
|||
}
|
||||
sb.append(condition.toString()).append('.');
|
||||
} else {
|
||||
sb.append(" [Condition toSting() == null] ");
|
||||
sb.append(" [Condition toString() == null] ");
|
||||
}
|
||||
return sb.toString() ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class BecomesExertSourceTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public BecomesExertSourceTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
}
|
||||
|
||||
public BecomesExertSourceTriggeredAbility(final BecomesExertSourceTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesExertSourceTriggeredAbility copy() {
|
||||
return new BecomesExertSourceTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.BECOMES_EXERTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getSourceId().equals(this.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} becomes exerted, " + super.getRule();
|
||||
}
|
||||
}
|
||||
|
|
@ -27,10 +27,10 @@
|
|||
*/
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.StateTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter.ComparisonType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
|
@ -69,24 +69,7 @@ public class ControlsPermanentsControllerTriggeredAbility extends StateTriggered
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
int inputValue = game.getBattlefield().countAll(filter, getControllerId(), game);
|
||||
switch (type) {
|
||||
case Equal:
|
||||
if (inputValue != value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case GreaterThan:
|
||||
if (inputValue <= value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case LessThan:
|
||||
if (inputValue >= value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return ComparisonType.compare(inputValue, type, value);
|
||||
}
|
||||
|
||||
@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.common;
|
||||
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public class CycleOrDiscardControllerTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public CycleOrDiscardControllerTriggeredAbility(Effect effect) {
|
||||
this(effect, false);
|
||||
}
|
||||
|
||||
public CycleOrDiscardControllerTriggeredAbility(Effect effect, boolean optional) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
}
|
||||
|
||||
public CycleOrDiscardControllerTriggeredAbility(final CycleOrDiscardControllerTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DISCARDED_CARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return event.getPlayerId().equals(controllerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever you cycle or discard a card, " + super.getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CycleOrDiscardControllerTriggeredAbility copy() {
|
||||
return new CycleOrDiscardControllerTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
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 stravant
|
||||
*/
|
||||
public class ExertCreatureControllerTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public ExertCreatureControllerTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect);
|
||||
}
|
||||
|
||||
public ExertCreatureControllerTriggeredAbility(final ExertCreatureControllerTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.BECOMES_EXERTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
boolean weAreExerting = getControllerId().equals(event.getPlayerId());
|
||||
Permanent exerted = game.getPermanent(event.getTargetId());
|
||||
boolean exertedIsCreature = (exerted != null) && exerted.isCreature();
|
||||
return weAreExerting && exertedIsCreature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExertCreatureControllerTriggeredAbility copy() {
|
||||
return new ExertCreatureControllerTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever you exert a creature, " + super.getRule();
|
||||
}
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ class LicidContinuousEffect extends ContinuousEffectImpl {
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
licid.getCardType().clear();
|
||||
licid.getCardType().add(CardType.ENCHANTMENT);
|
||||
licid.addCardType(CardType.ENCHANTMENT);
|
||||
licid.getSubtype(game).clear();
|
||||
licid.getSubtype(game).add("Aura");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package mage.abilities.condition;
|
||||
|
||||
import java.io.Serializable;
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Interface describing condition occurrence.
|
||||
|
|
@ -13,24 +14,6 @@ import mage.game.Game;
|
|||
@FunctionalInterface
|
||||
public interface Condition extends Serializable {
|
||||
|
||||
enum ComparisonType {
|
||||
|
||||
GreaterThan(">"),
|
||||
Equal("=="),
|
||||
LessThan("<");
|
||||
|
||||
private final String text;
|
||||
|
||||
ComparisonType(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the game to see if this condition applies for the given ability.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
package mage.abilities.condition;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
|
|
@ -36,10 +37,10 @@ import mage.game.Game;
|
|||
*/
|
||||
public abstract class IntCompareCondition implements Condition {
|
||||
|
||||
protected final Condition.ComparisonType type;
|
||||
protected final ComparisonType type;
|
||||
protected final int value;
|
||||
|
||||
public IntCompareCondition(Condition.ComparisonType type, int value) {
|
||||
public IntCompareCondition(ComparisonType type, int value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
|
@ -49,24 +50,7 @@ public abstract class IntCompareCondition implements Condition {
|
|||
@Override
|
||||
public final boolean apply(Game game, Ability source) {
|
||||
int inputValue = getInputValue(game, source);
|
||||
switch (type) {
|
||||
case Equal:
|
||||
if (inputValue != value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case GreaterThan:
|
||||
if (inputValue <= value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case LessThan:
|
||||
if (inputValue >= value) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return ComparisonType.compare(inputValue , type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -16,13 +16,9 @@ import mage.game.Game;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class BeforeBlockersAreDeclaredCondition implements Condition {
|
||||
public enum BeforeBlockersAreDeclaredCondition implements Condition {
|
||||
|
||||
private static final BeforeBlockersAreDeclaredCondition instance = new BeforeBlockersAreDeclaredCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -27,22 +27,23 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CardsInAnyLibraryCondition implements Condition {
|
||||
|
||||
protected final Condition.ComparisonType type;
|
||||
protected final ComparisonType type;
|
||||
protected final int value;
|
||||
|
||||
public CardsInAnyLibraryCondition(Condition.ComparisonType type, int value) {
|
||||
public CardsInAnyLibraryCondition(ComparisonType type, int value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
|
@ -54,23 +55,8 @@ public class CardsInAnyLibraryCondition implements Condition {
|
|||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
switch (type) {
|
||||
case GreaterThan:
|
||||
if (player.getLibrary().size() > value) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Equal:
|
||||
if (player.getLibrary().size() == value) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case LessThan:
|
||||
if (player.getLibrary().size() < value) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ComparisonType.compare(player.getLibrary().size(), type, value);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,13 +67,13 @@ public class CardsInAnyLibraryCondition implements Condition {
|
|||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("a library has ");
|
||||
switch (type) {
|
||||
case GreaterThan:
|
||||
case MORE_THAN:
|
||||
sb.append(value + 1).append(" or more cards in it ");
|
||||
break;
|
||||
case Equal:
|
||||
case EQUAL_TO:
|
||||
sb.append(value).append(" cards in it ");
|
||||
break;
|
||||
case LessThan:
|
||||
case FEWER_THAN:
|
||||
sb.append(value - 1).append(" or fewer cards in it ");
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ package mage.abilities.condition.common;
|
|||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.CountType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.TargetController;
|
||||
import mage.game.Game;
|
||||
|
|
@ -47,23 +47,23 @@ public class CardsInHandCondition implements Condition {
|
|||
|
||||
|
||||
private Condition condition;
|
||||
private CountType type;
|
||||
private ComparisonType type;
|
||||
private int count;
|
||||
private TargetController targetController;
|
||||
|
||||
public CardsInHandCondition() {
|
||||
this(CountType.EQUAL_TO, 0);
|
||||
this(ComparisonType.EQUAL_TO, 0);
|
||||
}
|
||||
|
||||
public CardsInHandCondition(CountType type, int count) {
|
||||
public CardsInHandCondition(ComparisonType type, int count) {
|
||||
this(type, count, null);
|
||||
}
|
||||
|
||||
public CardsInHandCondition(CountType type, int count, Condition conditionToDecorate) {
|
||||
public CardsInHandCondition(ComparisonType type, int count, Condition conditionToDecorate) {
|
||||
this(type, count, conditionToDecorate, TargetController.YOU);
|
||||
}
|
||||
|
||||
public CardsInHandCondition(CountType type, int count, Condition conditionToDecorate, TargetController targetController) {
|
||||
public CardsInHandCondition(ComparisonType type, int count, Condition conditionToDecorate, TargetController targetController) {
|
||||
this.type = type;
|
||||
this.count = count;
|
||||
this.condition = conditionToDecorate;
|
||||
|
|
@ -77,12 +77,12 @@ public class CardsInHandCondition implements Condition {
|
|||
if (controller != null) {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
conditionApplies = CountType.compare(game.getPlayer(source.getControllerId()).getHand().size(), type, count);
|
||||
conditionApplies = ComparisonType.compare(game.getPlayer(source.getControllerId()).getHand().size(), type, count);
|
||||
break;
|
||||
case ACTIVE:
|
||||
Player player = game.getPlayer(game.getActivePlayerId());
|
||||
if (player != null) {
|
||||
conditionApplies = CountType.compare(player.getHand().size(), type, count);
|
||||
conditionApplies = ComparisonType.compare(player.getHand().size(), type, count);
|
||||
}
|
||||
break;
|
||||
case ANY:
|
||||
|
|
@ -90,7 +90,7 @@ public class CardsInHandCondition implements Condition {
|
|||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
if (!CountType.compare(player.getHand().size(), type, this.count)) {
|
||||
if (!ComparisonType.compare(player.getHand().size(), type, this.count)) {
|
||||
conflict = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ import mage.watchers.common.CastFromHandWatcher;
|
|||
*
|
||||
* @author Loki
|
||||
*/
|
||||
public class CastFromHandSourceCondition implements Condition {
|
||||
public enum CastFromHandSourceCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -27,31 +27,22 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Checks if the player has its commander in play and controls it
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CommanderInPlayCondition implements Condition {
|
||||
public enum CommanderInPlayCondition implements Condition {
|
||||
|
||||
private static CommanderInPlayCondition instance = null;
|
||||
|
||||
private CommanderInPlayCondition() {
|
||||
}
|
||||
|
||||
public static Condition getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new CommanderInPlayCondition();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.IntCompareCondition;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DevourEffect;
|
||||
|
|
@ -43,7 +43,7 @@ import mage.game.permanent.Permanent;
|
|||
*/
|
||||
public class DevouredCreaturesCondition extends IntCompareCondition {
|
||||
|
||||
public DevouredCreaturesCondition(Condition.ComparisonType type, int value) {
|
||||
public DevouredCreaturesCondition(ComparisonType type, int value) {
|
||||
super(type, value);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,13 @@ package mage.abilities.condition.common;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
|
@ -40,15 +43,15 @@ import mage.game.permanent.Permanent;
|
|||
|
||||
public class EquippedHasSupertypeCondition implements Condition {
|
||||
|
||||
private String superType;
|
||||
private String[] superTypes; // scope = Any
|
||||
private SuperType superType;
|
||||
private EnumSet<SuperType> superTypes = EnumSet.noneOf(SuperType.class); // scope = Any
|
||||
|
||||
public EquippedHasSupertypeCondition(String subType) {
|
||||
this.superType = subType;
|
||||
public EquippedHasSupertypeCondition(SuperType supertype) {
|
||||
this.superType = supertype;
|
||||
}
|
||||
|
||||
public EquippedHasSupertypeCondition(String... subTypes) {
|
||||
this.superTypes = subTypes;
|
||||
public EquippedHasSupertypeCondition(EnumSet<SuperType> superTypes) {
|
||||
this.superTypes = superTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -61,12 +64,12 @@ public class EquippedHasSupertypeCondition implements Condition {
|
|||
}
|
||||
if (attachedTo != null) {
|
||||
if (superType != null) {
|
||||
if (attachedTo.getSupertype().contains(this.superType)) {
|
||||
if (attachedTo.getSuperType().contains(this.superType)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
for (String s : superTypes) {
|
||||
if (attachedTo.getSupertype().contains(s)) {
|
||||
for (SuperType s : superTypes) {
|
||||
if (attachedTo.getSuperType().contains(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,24 +27,21 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Describes condition when creature is equipped.
|
||||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class EquippedSourceCondition implements Condition {
|
||||
public enum EquippedSourceCondition implements Condition {
|
||||
|
||||
private static final EquippedSourceCondition instance = new EquippedSourceCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||
import mage.game.Game;
|
||||
|
|
@ -43,7 +43,7 @@ public enum FerociousCondition implements Condition {
|
|||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(new PowerPredicate(Filter.ComparisonType.GreaterThan, 3));
|
||||
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,13 +32,9 @@ import mage.abilities.condition.Condition;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
public class FlippedCondition implements Condition {
|
||||
public enum FlippedCondition implements Condition {
|
||||
|
||||
private static FlippedCondition instance = new FlippedCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author stravant
|
||||
*/
|
||||
public enum HeckbentCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return game.getPlayer(source.getControllerId()).getHand().size() <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "if you have one or fewer cards in hand";
|
||||
}
|
||||
}
|
||||
|
|
@ -8,15 +8,8 @@ import mage.watchers.common.LandfallWatcher;
|
|||
/**
|
||||
* @author Loki
|
||||
*/
|
||||
public class LandfallCondition implements Condition {
|
||||
private final static LandfallCondition instance = new LandfallCondition();
|
||||
|
||||
public static LandfallCondition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private LandfallCondition() {
|
||||
}
|
||||
public enum LandfallCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -35,13 +35,9 @@ import mage.game.Game;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MonarchIsSourceControllerCondition implements Condition {
|
||||
public enum MonarchIsSourceControllerCondition implements Condition {
|
||||
|
||||
private final static MonarchIsSourceControllerCondition instance = new MonarchIsSourceControllerCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import mage.players.Player;
|
|||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MoreCardsInHandThanOpponentsCondition implements Condition {
|
||||
public enum MoreCardsInHandThanOpponentsCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -37,12 +37,8 @@ import mage.game.Game;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MyTurnBeforeAttackersDeclaredCondition implements Condition {
|
||||
private static final MyTurnBeforeAttackersDeclaredCondition instance = new MyTurnBeforeAttackersDeclaredCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
public enum MyTurnBeforeAttackersDeclaredCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ package mage.abilities.condition.common;
|
|||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.CountType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
|
|
@ -48,18 +48,18 @@ public class OpponentControlsPermanentCondition implements Condition {
|
|||
|
||||
|
||||
private FilterPermanent filter;
|
||||
private CountType type;
|
||||
private ComparisonType type;
|
||||
private int count;
|
||||
|
||||
/**
|
||||
* @param filter
|
||||
*/
|
||||
public OpponentControlsPermanentCondition(FilterPermanent filter) {
|
||||
this(filter, CountType.MORE_THAN, 0);
|
||||
this(filter, ComparisonType.MORE_THAN, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a filter, a {@link CountType}, and count to permanents on the
|
||||
* Applies a filter, a {@link ComparisonType}, and count to permanents on the
|
||||
* battlefield when checking the condition during the
|
||||
* {@link #apply(mage.game.Game, mage.abilities.Ability) apply} method invocation.
|
||||
*
|
||||
|
|
@ -67,7 +67,7 @@ public class OpponentControlsPermanentCondition implements Condition {
|
|||
* @param type
|
||||
* @param count
|
||||
*/
|
||||
public OpponentControlsPermanentCondition(FilterPermanent filter, CountType type, int count) {
|
||||
public OpponentControlsPermanentCondition(FilterPermanent filter, ComparisonType type, int count) {
|
||||
this.filter = filter;
|
||||
this.type = type;
|
||||
this.count = count;
|
||||
|
|
@ -79,7 +79,7 @@ public class OpponentControlsPermanentCondition implements Condition {
|
|||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
FilterPermanent localFilter = filter.copy();
|
||||
localFilter.add(new ControllerIdPredicate(opponentId));
|
||||
if (CountType.compare(game.getBattlefield().count(localFilter, source.getSourceId(), source.getControllerId(), game), type, this.count)) {
|
||||
if (ComparisonType.compare(game.getBattlefield().count(localFilter, source.getSourceId(), source.getControllerId(), game), type, this.count)) {
|
||||
conditionApplies = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,21 +28,21 @@
|
|||
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
|
||||
public class OpponentHasMoreLifeCondition implements Condition {
|
||||
public enum OpponentHasMoreLifeCondition implements Condition {
|
||||
|
||||
public OpponentHasMoreLifeCondition() {
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.IntCompareCondition;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.PlayerLostLifeWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Describes condition when an opponent has lost an amount of life
|
||||
*
|
||||
|
|
@ -42,7 +42,7 @@ import mage.watchers.common.PlayerLostLifeWatcher;
|
|||
*/
|
||||
public class OpponentLostLifeCondition extends IntCompareCondition {
|
||||
|
||||
public OpponentLostLifeCondition(Condition.ComparisonType type, int value) {
|
||||
public OpponentLostLifeCondition(ComparisonType type, int value) {
|
||||
super(type, value);
|
||||
}
|
||||
|
||||
|
|
@ -65,13 +65,13 @@ public class OpponentLostLifeCondition extends IntCompareCondition {
|
|||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("if an opponent lost ");
|
||||
switch (type) {
|
||||
case GreaterThan:
|
||||
case MORE_THAN:
|
||||
sb.append(value + 1).append(" or more life this turn ");
|
||||
break;
|
||||
case Equal:
|
||||
case EQUAL_TO:
|
||||
sb.append(value).append(" life this turn ");
|
||||
break;
|
||||
case LessThan:
|
||||
case FEWER_THAN:
|
||||
sb.append(" less than ").append(value).append(" life this turn ");
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.CountType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
|
|
@ -47,15 +47,15 @@ public class PermanentHasCounterCondition implements Condition {
|
|||
private CounterType counterType;
|
||||
private int amount;
|
||||
private FilterPermanent filter;
|
||||
private CountType counttype;
|
||||
private ComparisonType counttype;
|
||||
private boolean anyPlayer;
|
||||
|
||||
public PermanentHasCounterCondition(CounterType counterType, int amount, FilterPermanent filter) {
|
||||
this(counterType, amount, filter, CountType.EQUAL_TO);
|
||||
this(counterType, amount, filter, ComparisonType.EQUAL_TO);
|
||||
this.anyPlayer = false;
|
||||
}
|
||||
|
||||
public PermanentHasCounterCondition(CounterType counterType, int amount, FilterPermanent filter, CountType type) {
|
||||
public PermanentHasCounterCondition(CounterType counterType, int amount, FilterPermanent filter, ComparisonType type) {
|
||||
this.counterType = counterType;
|
||||
this.amount = amount;
|
||||
this.filter = filter;
|
||||
|
|
@ -63,7 +63,7 @@ public class PermanentHasCounterCondition implements Condition {
|
|||
this.anyPlayer = false;
|
||||
}
|
||||
|
||||
public PermanentHasCounterCondition(CounterType counterType, int amount, FilterPermanent filter, CountType type, boolean any) {
|
||||
public PermanentHasCounterCondition(CounterType counterType, int amount, FilterPermanent filter, ComparisonType type, boolean any) {
|
||||
this.counterType = counterType;
|
||||
this.amount = amount;
|
||||
this.filter = filter;
|
||||
|
|
@ -77,7 +77,7 @@ public class PermanentHasCounterCondition implements Condition {
|
|||
permanents = game.getBattlefield().getAllActivePermanents(this.filter, game);
|
||||
}
|
||||
for (Permanent permanent : permanents) {
|
||||
if(CountType.compare(permanent.getCounters(game).getCount(this.counterType), counttype, this.amount))
|
||||
if(ComparisonType.compare(permanent.getCounters(game).getCount(this.counterType), counttype, this.amount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.CountType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
|
|
@ -47,23 +47,23 @@ public class PermanentsOnTheBattlefieldCondition implements Condition {
|
|||
|
||||
private FilterPermanent filter;
|
||||
private Condition condition;
|
||||
private CountType type;
|
||||
private ComparisonType type;
|
||||
private int count;
|
||||
private boolean onlyControlled;
|
||||
|
||||
/**
|
||||
* Applies a filter and delegates creation to
|
||||
* {@link #ControlsPermanent(mage.filter.FilterPermanent, mage.abilities.condition.common.ControlsPermanent.CountType, int)}
|
||||
* with {@link CountType#MORE_THAN}, and 0.
|
||||
* with {@link ComparisonType#MORE_THAN}, and 0.
|
||||
*
|
||||
* @param filter
|
||||
*/
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter) {
|
||||
this(filter, CountType.MORE_THAN, 0);
|
||||
this(filter, ComparisonType.MORE_THAN, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a filter, a {@link CountType}, and count to permanents on the
|
||||
* Applies a filter, a {@link ComparisonType}, and count to permanents on the
|
||||
* battlefield when checking the condition during the
|
||||
* {@link #apply(mage.game.Game, mage.abilities.Ability) apply} method invocation.
|
||||
*
|
||||
|
|
@ -71,11 +71,11 @@ public class PermanentsOnTheBattlefieldCondition implements Condition {
|
|||
* @param type
|
||||
* @param count
|
||||
*/
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter, CountType type, int count) {
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter, ComparisonType type, int count) {
|
||||
this(filter, type, count, true);
|
||||
}
|
||||
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter, CountType type, int count, boolean onlyControlled) {
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter, ComparisonType type, int count, boolean onlyControlled) {
|
||||
this.filter = filter;
|
||||
this.type = type;
|
||||
this.count = count;
|
||||
|
|
@ -83,7 +83,7 @@ public class PermanentsOnTheBattlefieldCondition implements Condition {
|
|||
}
|
||||
|
||||
/**
|
||||
* Applies a filter, a {@link CountType}, and count to permanents on the
|
||||
* Applies a filter, a {@link ComparisonType}, and count to permanents on the
|
||||
* battlefield and calls the decorated condition to see if it
|
||||
* {@link #apply(mage.game.Game, mage.abilities.Ability) applies}
|
||||
* as well. This will force both conditions to apply for this to be true.
|
||||
|
|
@ -93,7 +93,7 @@ public class PermanentsOnTheBattlefieldCondition implements Condition {
|
|||
* @param count
|
||||
* @param conditionToDecorate
|
||||
*/
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter, CountType type, int count, Condition conditionToDecorate) {
|
||||
public PermanentsOnTheBattlefieldCondition(FilterPermanent filter, ComparisonType type, int count, Condition conditionToDecorate) {
|
||||
this(filter, type, count);
|
||||
this.condition = conditionToDecorate;
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ public class PermanentsOnTheBattlefieldCondition implements Condition {
|
|||
}
|
||||
|
||||
int permanentsOnBattlefield = game.getBattlefield().count(localFilter, source.getSourceId(), source.getControllerId(), game);
|
||||
conditionApplies = CountType.compare(permanentsOnBattlefield, type, count);
|
||||
conditionApplies = ComparisonType.compare(permanentsOnBattlefield, type, count);
|
||||
|
||||
//If a decorated condition exists, check it as well and apply them together.
|
||||
if (this.condition != null) {
|
||||
|
|
|
|||
|
|
@ -36,19 +36,9 @@ import mage.game.permanent.Permanent;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RenownedTargetCondition implements Condition {
|
||||
public enum RenownedTargetCondition implements Condition {
|
||||
|
||||
private static RenownedTargetCondition instance = null;
|
||||
|
||||
private RenownedTargetCondition() {
|
||||
}
|
||||
|
||||
public static RenownedTargetCondition getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new RenownedTargetCondition();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -37,13 +37,9 @@ import mage.game.permanent.Permanent;
|
|||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class SourceAttackingCondition implements Condition {
|
||||
public enum SourceAttackingCondition implements Condition {
|
||||
|
||||
private static final SourceAttackingCondition instance = new SourceAttackingCondition();
|
||||
|
||||
public static SourceAttackingCondition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class SourceHasCounterCondition implements Condition {
|
||||
|
|
@ -82,12 +82,26 @@ public class SourceHasCounterCondition implements Condition {
|
|||
return count >= from;
|
||||
}
|
||||
return count >= from && count <= to;
|
||||
} else { // single compare (lte)
|
||||
} else // single compare (lte)
|
||||
{
|
||||
if (card != null) {
|
||||
return card.getCounters(game).getCount(counterType) >= amount;
|
||||
} else {
|
||||
} else {
|
||||
return permanent.getCounters(game).getCount(counterType) >= amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (from != -1) { //range compare
|
||||
if (to == Integer.MAX_VALUE) {
|
||||
return "{this} has equal to or more than " + from + " " + this.counterType.toString() + " counters";
|
||||
}
|
||||
return "{this} has between " + from + " and " + to + " " + this.counterType.toString() + " counters";
|
||||
} else // single compare (lte)
|
||||
{
|
||||
return "{this} has equal or more than " + amount + " " + this.counterType.toString() + " counters";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,13 +38,9 @@ import mage.game.Game;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class SourceOnBattlefieldCondition implements Condition {
|
||||
public enum SourceOnBattlefieldCondition implements Condition {
|
||||
|
||||
private static final SourceOnBattlefieldCondition instance = new SourceOnBattlefieldCondition();
|
||||
|
||||
public static SourceOnBattlefieldCondition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.constants.PhaseStep;
|
||||
|
|
@ -37,6 +36,8 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.game.turn.Step;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
|
|
@ -44,15 +45,11 @@ import mage.game.turn.Step;
|
|||
|
||||
public class SourceTappedBeforeUntapStepCondition implements Condition {
|
||||
|
||||
private static final SourceTappedBeforeUntapStepCondition instance = new SourceTappedBeforeUntapStepCondition();
|
||||
UUID permanentId = null;
|
||||
boolean permanentWasTappedBeforeUntapStep = false;
|
||||
int lastTurnNum = -1;
|
||||
|
||||
|
||||
public static SourceTappedBeforeUntapStepCondition getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void setPermanentId(UUID permanentId) {
|
||||
this.permanentId = permanentId;
|
||||
|
|
|
|||
|
|
@ -45,18 +45,9 @@ import mage.game.Game;
|
|||
*
|
||||
*/
|
||||
|
||||
public class SuspendedCondition implements Condition {
|
||||
public enum SuspendedCondition implements Condition {
|
||||
|
||||
private static SuspendedCondition instance = null;
|
||||
|
||||
private SuspendedCondition() {}
|
||||
|
||||
public static Condition getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new SuspendedCondition();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
|
|
@ -42,7 +43,7 @@ public enum TargetAttackedThisTurnCondition implements Condition {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = game.getPermanentOrLKIBattlefield(source.getTargets().getFirstTarget());
|
||||
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get("AttackedThisTurn");
|
||||
return watcher.getAttackedThisTurnCreatures().contains(creature.getId());
|
||||
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getName());
|
||||
return watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(creature, game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,25 +27,28 @@
|
|||
*/
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerList;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author maurer.it_at_gmail.com
|
||||
*/
|
||||
public class TenOrLessLifeCondition implements Condition {
|
||||
public class XorLessLifeCondition implements Condition {
|
||||
|
||||
public enum CheckType { AN_OPPONENT, CONTROLLER, TARGET_OPPONENT, EACH_PLAYER }
|
||||
|
||||
private final CheckType type;
|
||||
private final int amount;
|
||||
|
||||
public TenOrLessLifeCondition ( CheckType type ) {
|
||||
public XorLessLifeCondition ( CheckType type , int amount) {
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -55,11 +58,11 @@ public class TenOrLessLifeCondition implements Condition {
|
|||
switch ( this.type ) {
|
||||
case AN_OPPONENT:
|
||||
for ( UUID opponentUUID : game.getOpponents(source.getControllerId()) ) {
|
||||
conditionApplies |= game.getPlayer(opponentUUID).getLife() <= 10;
|
||||
conditionApplies |= game.getPlayer(opponentUUID).getLife() <= amount;
|
||||
}
|
||||
break;
|
||||
case CONTROLLER:
|
||||
conditionApplies |= game.getPlayer(source.getControllerId()).getLife() <= 10;
|
||||
conditionApplies |= game.getPlayer(source.getControllerId()).getLife() <= amount;
|
||||
break;
|
||||
case TARGET_OPPONENT:
|
||||
//TODO: Implement this.
|
||||
|
|
@ -71,11 +74,11 @@ public class TenOrLessLifeCondition implements Condition {
|
|||
Player p = game.getPlayer(pid);
|
||||
if (p != null) {
|
||||
if (maxLife < p.getLife()) {
|
||||
maxLife = p.getLife();
|
||||
maxLife = p.getLife();
|
||||
}
|
||||
}
|
||||
}
|
||||
conditionApplies |= maxLife <= 10;
|
||||
conditionApplies |= maxLife <= amount;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.condition.IntCompareCondition;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.PlayerGainedLifeWatcher;
|
||||
|
||||
/**
|
||||
* Created by IGOUDT on 5-4-2017.
|
||||
*/
|
||||
public class YouGainedLifeCondition extends IntCompareCondition {
|
||||
|
||||
public YouGainedLifeCondition(ComparisonType type, int value) {
|
||||
super(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getInputValue(Game game, Ability source) {
|
||||
int gainedLife = 0;
|
||||
PlayerGainedLifeWatcher watcher = (PlayerGainedLifeWatcher) game.getState().getWatchers().get(PlayerGainedLifeWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
gainedLife = watcher.getLiveGained(source.getControllerId());
|
||||
}
|
||||
return gainedLife;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("if you gained %s or more life this turn ", value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +29,9 @@ package mage.abilities.costs;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.Targets;
|
||||
|
|
@ -131,13 +133,15 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
return true; /* not used */
|
||||
return true;
|
||||
/* not used */
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
return true; /* not used */
|
||||
return true;
|
||||
/* not used */
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +169,9 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
public int announceXValue(Ability source, Game game) {
|
||||
int xValue = 0;
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
||||
if (controller != null
|
||||
&& (source instanceof FlashbackAbility || stackObject != null)) {
|
||||
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
|
||||
"Announce the number of " + actionText, game, source, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -40,7 +39,6 @@ import mage.target.common.TargetCardInHand;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class DiscardXTargetCost extends VariableCostImpl {
|
||||
|
||||
protected FilterCard filter;
|
||||
|
|
@ -50,9 +48,8 @@ public class DiscardXTargetCost extends VariableCostImpl {
|
|||
}
|
||||
|
||||
public DiscardXTargetCost(FilterCard filter, boolean additionalCostText) {
|
||||
super(new StringBuilder(filter.getMessage()).append(" to discard").toString());
|
||||
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, discard ":"Discard ")
|
||||
.append(xText).append(' ').append(filter.getMessage()).toString();
|
||||
super(filter.getMessage() + " to discard");
|
||||
this.text = (additionalCostText ? "As an additional cost to cast {source}, discard " : "Discard ") + xText + ' ' + filter.getMessage();
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import mage.Mana;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterObject;
|
||||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||
import mage.game.Game;
|
||||
|
|
@ -41,7 +42,7 @@ public class SnowManaCost extends ManaCostImpl {
|
|||
private static final FilterObject filter = new FilterObject("Snow object");
|
||||
|
||||
static {
|
||||
filter.add(new SupertypePredicate("Snow"));
|
||||
filter.add(new SupertypePredicate(SuperType.SNOW));
|
||||
}
|
||||
|
||||
public SnowManaCost() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package mage.abilities.dynamicvalue.common;
|
||||
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author stravant
|
||||
*/
|
||||
public class EffectKeyValue implements DynamicValue {
|
||||
private String key;
|
||||
private String description;
|
||||
|
||||
public EffectKeyValue(String key) {
|
||||
this.key = key;
|
||||
this.description = key;
|
||||
}
|
||||
|
||||
public EffectKeyValue(String key, String description) {
|
||||
this(key);
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability source, Effect effect) {
|
||||
return (Integer)effect.getValue(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EffectKeyValue copy(){
|
||||
return new EffectKeyValue(this.key, this.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "equal to";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,15 @@ import mage.players.ManaPoolItem;
|
|||
public interface AsThoughManaEffect extends AsThoughEffect {
|
||||
|
||||
// return a mana type that can be used to pay a mana cost instead of the normally needed mana type
|
||||
/**
|
||||
*
|
||||
* @param manaType type of mana with which the player wants to pay the cost
|
||||
* @param mana mana pool item to pay from the cost
|
||||
* @param affectedControllerId
|
||||
* @param source
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.keyword.SpliceOntoArcaneAbility;
|
||||
|
|
@ -49,10 +52,6 @@ import mage.players.Player;
|
|||
import mage.target.common.TargetCardInHand;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -691,8 +690,7 @@ public class ContinuousEffects implements Serializable {
|
|||
spliceAbilities.remove(selectedAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", abilityToModify, game));
|
||||
} while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", abilityToModify, game));
|
||||
controller.revealCards("Spliced cards", cardsToReveal, game);
|
||||
}
|
||||
}
|
||||
|
|
@ -702,10 +700,10 @@ public class ContinuousEffects implements Serializable {
|
|||
* Checks if an event won't happen because of an rule modifying effect
|
||||
*
|
||||
* @param event
|
||||
* @param targetAbility ability the event is attached to. can be null.
|
||||
* @param targetAbility ability the event is attached to. can be null.
|
||||
* @param game
|
||||
* @param checkPlayableMode true if the event does not really happen but
|
||||
* it's checked if the event would be replaced
|
||||
* it's checked if the event would be replaced
|
||||
* @return
|
||||
*/
|
||||
public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean checkPlayableMode) {
|
||||
|
|
@ -752,7 +750,7 @@ public class ContinuousEffects implements Serializable {
|
|||
do {
|
||||
HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game);
|
||||
// Remove all consumed effects (ability dependant)
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext(); ) {
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
|
||||
ReplacementEffect entry = it1.next();
|
||||
if (consumed.containsKey(entry.getId())) {
|
||||
HashSet<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
|
||||
|
|
@ -933,7 +931,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
if (!waitingEffects.isEmpty()) {
|
||||
// check if waiting effects can be applied now
|
||||
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<ContinuousEffect, Set<UUID>> entry = iterator.next();
|
||||
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
|
||||
appliedAbilities = appliedEffectAbilities.get(entry.getKey());
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public interface Effect extends Serializable {
|
|||
UUID getId();
|
||||
void newId();
|
||||
String getText(Mode mode);
|
||||
void setText(String staticText);
|
||||
Effect setText(String staticText);
|
||||
boolean apply(Game game, Ability source);
|
||||
Outcome getOutcome();
|
||||
void setOutcome(Outcome outcome);
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ public abstract class EffectImpl implements Effect {
|
|||
public EffectImpl(final EffectImpl effect) {
|
||||
this.id = effect.id;
|
||||
this.outcome = effect.outcome;
|
||||
this.effectType = effect.effectType;
|
||||
this.staticText = effect.staticText;
|
||||
this.effectType = effect.effectType;
|
||||
this.targetPointer = effect.targetPointer.copy();
|
||||
if (effect.values != null) {
|
||||
values = new HashMap<>();
|
||||
|
|
@ -85,8 +85,9 @@ public abstract class EffectImpl implements Effect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setText(String staticText) {
|
||||
public Effect setText(String staticText) {
|
||||
this.staticText = staticText;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
if (spell != null) {
|
||||
effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility());
|
||||
}
|
||||
effect.setValue("appliedEffects", event.getAppliedEffects());
|
||||
effect.apply(game, source);
|
||||
}
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -27,25 +27,20 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.util.functions.ApplyToPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -128,15 +123,15 @@ public class CopyEffect extends ContinuousEffectImpl {
|
|||
permanent.getManaCost().add(copyFromObject.getManaCost());
|
||||
permanent.getCardType().clear();
|
||||
for (CardType type : copyFromObject.getCardType()) {
|
||||
permanent.getCardType().add(type);
|
||||
permanent.addCardType(type);
|
||||
}
|
||||
permanent.getSubtype(game).clear();
|
||||
for (String type : copyFromObject.getSubtype(game)) {
|
||||
permanent.getSubtype(game).add(type);
|
||||
}
|
||||
permanent.getSupertype().clear();
|
||||
for (String type : copyFromObject.getSupertype()) {
|
||||
permanent.getSupertype().add(type);
|
||||
permanent.getSuperType().clear();
|
||||
for (SuperType type : copyFromObject.getSuperType()) {
|
||||
permanent.addSuperType(type);
|
||||
}
|
||||
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@ package mage.abilities.effects.common;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
|
@ -32,15 +28,15 @@ public class CopyTokenEffect extends ContinuousEffectImpl {
|
|||
permanent.getColor(game).setColor(token.getColor(game));
|
||||
permanent.getCardType().clear();
|
||||
for (CardType type: token.getCardType()) {
|
||||
permanent.getCardType().add(type);
|
||||
permanent.addCardType(type);
|
||||
}
|
||||
permanent.getSubtype(game).clear();
|
||||
for (String type: token.getSubtype(game)) {
|
||||
permanent.getSubtype(game).add(type);
|
||||
}
|
||||
permanent.getSupertype().clear();
|
||||
for (String type: token.getSupertype()) {
|
||||
permanent.getSupertype().add(type);
|
||||
permanent.getSuperType().clear();
|
||||
for (SuperType type: token.getSuperType()) {
|
||||
permanent.addSuperType(type);
|
||||
}
|
||||
permanent.getAbilities().clear();
|
||||
for (Ability ability: token.getAbilities()) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class EndTurnEffect extends OneShotEffect {
|
|||
if (!game.isSimulation()) {
|
||||
game.informPlayers("The current turn ends");
|
||||
}
|
||||
return game.endTurn();
|
||||
return game.endTurn(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.EntersBattlefieldEffect;
|
||||
|
|
@ -75,7 +77,8 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect {
|
|||
if (amount > 0) {
|
||||
Counter counterToAdd = counter.copy();
|
||||
counterToAdd.add(amount - counter.getCount());
|
||||
permanent.addCounters(counterToAdd, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
permanent.addCounters(counterToAdd, source, game, appliedEffects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,8 @@ public class ExileTargetEffect extends OneShotEffect {
|
|||
sb.append("target ");
|
||||
}
|
||||
sb.append(targetName);
|
||||
} else if (target.getNumberOfTargets() == 0 && target.getMaxNumberOfTargets() > 0) {
|
||||
sb.append("exile up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(" target ").append(target.getTargetName());
|
||||
} else {
|
||||
sb.append("exile ").append(CardUtil.numberToText(target.getNumberOfTargets())).append(" target ").append(target.getTargetName());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ package mage.abilities.effects.common;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class FlipSourceEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (permanent != null && controller != null) {
|
||||
if (permanent.flip(game)) {
|
||||
ContinuousEffect effect = new ConditionalContinuousEffect(new CopyTokenEffect(flipToken), FlippedCondition.getInstance(), "");
|
||||
ContinuousEffect effect = new ConditionalContinuousEffect(new CopyTokenEffect(flipToken), FlippedCondition.instance, "");
|
||||
game.addEffect(effect, source);
|
||||
if (!game.isSimulation())
|
||||
game.informPlayers(new StringBuilder(controller.getLogName()).append(" flips ").append(permanent.getName()).toString());
|
||||
|
|
|
|||
|
|
@ -50,10 +50,11 @@ public class NameACardEffect extends OneShotEffect {
|
|||
public enum TypeOfName {
|
||||
|
||||
ALL,
|
||||
NON_ARTFIACT_AND_NON_LAND_NAME,
|
||||
NON_ARTIFACT_AND_NON_LAND_NAME,
|
||||
NON_LAND_NAME,
|
||||
NON_LAND_AND_NON_CREATURE_NAME,
|
||||
CREATURE_NAME
|
||||
CREATURE_NAME,
|
||||
ARTIFACT_NAME
|
||||
}
|
||||
|
||||
private final TypeOfName typeOfName;
|
||||
|
|
@ -83,7 +84,7 @@ public class NameACardEffect extends OneShotEffect {
|
|||
cardChoice.setChoices(CardRepository.instance.getNames());
|
||||
cardChoice.setMessage("Name a card");
|
||||
break;
|
||||
case NON_ARTFIACT_AND_NON_LAND_NAME:
|
||||
case NON_ARTIFACT_AND_NON_LAND_NAME:
|
||||
cardChoice.setChoices(CardRepository.instance.getNonArtifactAndNonLandNames());
|
||||
cardChoice.setMessage("Name a non artifact and non land card");
|
||||
break;
|
||||
|
|
@ -99,6 +100,10 @@ public class NameACardEffect extends OneShotEffect {
|
|||
cardChoice.setChoices(CardRepository.instance.getCreatureNames());
|
||||
cardChoice.setMessage("Name a creature card");
|
||||
break;
|
||||
case ARTIFACT_NAME:
|
||||
cardChoice.setChoices(CardRepository.instance.getArtifactNames());
|
||||
cardChoice.setMessage("Name an artifact card");
|
||||
break;
|
||||
}
|
||||
cardChoice.clearChoice();
|
||||
while (!controller.choose(Outcome.Detriment, cardChoice, game)) {
|
||||
|
|
@ -130,7 +135,7 @@ public class NameACardEffect extends OneShotEffect {
|
|||
case ALL:
|
||||
sb.append("card");
|
||||
break;
|
||||
case NON_ARTFIACT_AND_NON_LAND_NAME:
|
||||
case NON_ARTIFACT_AND_NON_LAND_NAME:
|
||||
sb.append("nonartifact, nonland card");
|
||||
break;
|
||||
case NON_LAND_AND_NON_CREATURE_NAME:
|
||||
|
|
@ -139,6 +144,12 @@ public class NameACardEffect extends OneShotEffect {
|
|||
case NON_LAND_NAME:
|
||||
sb.append("nonland card");
|
||||
break;
|
||||
case CREATURE_NAME:
|
||||
sb.append("creature card");
|
||||
break;
|
||||
case ARTIFACT_NAME:
|
||||
sb.append("artifact card");
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,12 +188,12 @@ public class PutTokenOntoBattlefieldCopyTargetEffect extends OneShotEffect {
|
|||
|
||||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(copyFrom); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||
applier.apply(game, token);
|
||||
applier.apply(game, token, source, targetId);
|
||||
if (becomesArtifact) {
|
||||
token.getCardType().add(CardType.ARTIFACT);
|
||||
token.addCardType(CardType.ARTIFACT);
|
||||
}
|
||||
if (additionalCardType != null && !token.getCardType().contains(additionalCardType)) {
|
||||
token.getCardType().add(additionalCardType);
|
||||
token.addCardType(additionalCardType);
|
||||
}
|
||||
if (gainsHaste) {
|
||||
token.addAbility(HasteAbility.getInstance());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.costs.common.DiscardCardCost;
|
||||
|
||||
/**
|
||||
* @author stravant
|
||||
*/
|
||||
public class RummageEffect extends DoIfCostPaid {
|
||||
public RummageEffect() {
|
||||
super(new DrawCardSourceControllerEffect(1), new DiscardCardCost());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class SendOptionUsedEventEffect extends OneShotEffect {
|
||||
|
||||
private final int value;
|
||||
|
||||
public SendOptionUsedEventEffect() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public SendOptionUsedEventEffect(int value) {
|
||||
super(Outcome.Detriment);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public SendOptionUsedEventEffect(final SendOptionUsedEventEffect effect) {
|
||||
super(effect);
|
||||
this.value = effect.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendOptionUsedEventEffect copy() {
|
||||
return new SendOptionUsedEventEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.OPTION_USED, source.getOriginalId(), source.getSourceId(), source.getControllerId(), value));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -44,32 +44,42 @@ import mage.players.Player;
|
|||
public class UntapAllControllerEffect extends OneShotEffect {
|
||||
|
||||
private final FilterPermanent filter;
|
||||
private final boolean includeSource;
|
||||
|
||||
public UntapAllControllerEffect(FilterPermanent filter) {
|
||||
this(filter, null);
|
||||
}
|
||||
|
||||
public UntapAllControllerEffect(FilterPermanent filter, String rule) {
|
||||
this(filter, rule, true);
|
||||
}
|
||||
|
||||
public UntapAllControllerEffect(FilterPermanent filter, String rule, boolean includeSource) {
|
||||
super(Outcome.Untap);
|
||||
if (rule == null || rule.isEmpty()) {
|
||||
staticText = "untap all " + filter.getMessage() + " you control";
|
||||
staticText = "untap all " + (includeSource ? "" : "other ") + filter.getMessage() + " you control";
|
||||
} else {
|
||||
staticText = rule;
|
||||
}
|
||||
this.filter = filter;
|
||||
this.includeSource = includeSource;
|
||||
}
|
||||
|
||||
public UntapAllControllerEffect(final UntapAllControllerEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
this.includeSource = effect.includeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (player != null) {
|
||||
for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, player.getId(), game)) {
|
||||
permanent.untap(game);
|
||||
if (includeSource || sourcePermanent == null || !sourcePermanent.getId().equals(permanent.getId())) {
|
||||
permanent.untap(game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,9 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -63,11 +62,11 @@ public class UntapAllThatAttackedEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Watcher watcher = game.getState().getWatchers().get("AttackedThisTurn");
|
||||
Watcher watcher = game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher instanceof AttackedThisTurnWatcher) {
|
||||
Set<UUID> attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures();
|
||||
for (UUID uuid : attackedThisTurn) {
|
||||
Permanent permanent = game.getPermanent(uuid);
|
||||
Set<MageObjectReference> attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures();
|
||||
for (MageObjectReference mor : attackedThisTurn) {
|
||||
Permanent permanent = mor.getPermanent(game);
|
||||
if (permanent != null && permanent.isCreature()) {
|
||||
permanent.untap(game);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public class UntapTargetEffect extends OneShotEffect {
|
|||
Target target = mode.getTargets().get(0);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Untap ");
|
||||
sb.append("untap ");
|
||||
if (target.getNumberOfTargets() == 0) {
|
||||
sb.append("up to ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package mage.abilities.effects.common.combat;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -59,8 +60,8 @@ public class AttacksIfAbleAllEffect extends RequirementEffect {
|
|||
if (eachCombat) {
|
||||
return true;
|
||||
}
|
||||
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get("AttackedThisTurn");
|
||||
return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(permanent.getId());
|
||||
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getName());
|
||||
return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,17 +20,17 @@
|
|||
* 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.combat;
|
||||
|
||||
import mage.constants.Duration;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.common.AttackedThisTurnWatcher;
|
||||
|
|
@ -42,18 +42,18 @@ import mage.watchers.common.AttackedThisTurnWatcher;
|
|||
public class AttacksIfAbleSourceEffect extends RequirementEffect {
|
||||
|
||||
boolean eachCombat;
|
||||
|
||||
|
||||
public AttacksIfAbleSourceEffect(Duration duration) {
|
||||
this(duration, false);
|
||||
this(duration, false);
|
||||
}
|
||||
|
||||
|
||||
public AttacksIfAbleSourceEffect(Duration duration, boolean eachCombat) {
|
||||
super(duration);
|
||||
this.eachCombat = eachCombat;
|
||||
if (this.duration == Duration.EndOfTurn) {
|
||||
staticText = "{this} attacks " + (eachCombat ? "each combat" :"this turn") + " if able";
|
||||
staticText = "{this} attacks " + (eachCombat ? "each combat" : "this turn") + " if able";
|
||||
} else {
|
||||
staticText = "{this} attacks each " + (eachCombat ? "combat" :"turn") + " if able";
|
||||
staticText = "{this} attacks each " + (eachCombat ? "combat" : "turn") + " if able";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,8 +73,8 @@ public class AttacksIfAbleSourceEffect extends RequirementEffect {
|
|||
if (eachCombat) {
|
||||
return true;
|
||||
}
|
||||
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher)game.getState().getWatchers().get("AttackedThisTurn");
|
||||
return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(permanent.getId());
|
||||
AttackedThisTurnWatcher watcher = (AttackedThisTurnWatcher) game.getState().getWatchers().get(AttackedThisTurnWatcher.class.getName());
|
||||
return watcher != null && !watcher.getAttackedThisTurnCreatures().contains(new MageObjectReference(permanent, game));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class AddCardTypeAttachedEffect extends ContinuousEffectImpl {
|
|||
if (equipment != null && equipment.getAttachedTo() != null) {
|
||||
Permanent target = game.getPermanent(equipment.getAttachedTo());
|
||||
if (target != null && !target.getCardType().contains(addedCardType))
|
||||
target.getCardType().add(addedCardType);
|
||||
target.addCardType(addedCardType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,7 @@ public class AddCardTypeSourceEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && affectedObjectList.contains(new MageObjectReference(permanent, game))) {
|
||||
if (!permanent.getCardType().contains(addedCardType)) {
|
||||
permanent.getCardType().add(addedCardType);
|
||||
}
|
||||
permanent.addCardType(addedCardType);
|
||||
return true;
|
||||
} else if (this.getDuration() == Duration.Custom) {
|
||||
this.discard();
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public class AddCardTypeTargetEffect extends ContinuousEffectImpl {
|
|||
Permanent target = game.getPermanent(targetId);
|
||||
if (target != null) {
|
||||
if (!target.getCardType().contains(addedCardType)) {
|
||||
target.getCardType().add(addedCardType);
|
||||
target.addCardType(addedCardType);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
|
|||
case TypeChangingEffects_4:
|
||||
// Attention: Cards like Unstable Frontier that use this class do not give the "Basic" supertype to the target
|
||||
if (!land.isLand()) {
|
||||
land.getCardType().add(CardType.LAND);
|
||||
land.addCardType(CardType.LAND);
|
||||
}
|
||||
if (loseOther) {
|
||||
// 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
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 JRHerlehy
|
||||
* Created on 4/8/17.
|
||||
*/
|
||||
public class BecomesBlackZombieAdditionEffect extends ContinuousEffectImpl {
|
||||
|
||||
public BecomesBlackZombieAdditionEffect() {
|
||||
super(Duration.Custom, Outcome.Neutral);
|
||||
staticText = "That creature is a black Zombie in addition to its other colors and types";
|
||||
}
|
||||
|
||||
public BecomesBlackZombieAdditionEffect(final BecomesBlackZombieAdditionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||
if (creature != null) {
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (!creature.getSubtype(game).contains("Zombie")) {
|
||||
creature.getSubtype(game).add("Zombie");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ColorChangingEffects_5:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
creature.getColor(game).setBlack(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
this.used = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesBlackZombieAdditionEffect copy() {
|
||||
return new BecomesBlackZombieAdditionEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
if (!token.getCardType().isEmpty()) {
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.getCardType().add(t);
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,11 +30,7 @@ package mage.abilities.effects.common.continuous;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
|
@ -85,10 +81,9 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
for (String t : token.getSupertype()) {
|
||||
if (!permanent.getSupertype().contains(t)) {
|
||||
permanent.getSupertype().add(t);
|
||||
}
|
||||
for (SuperType t : token.getSuperType()) {
|
||||
permanent.addSuperType(t);
|
||||
|
||||
}
|
||||
// card type
|
||||
switch (loseType) {
|
||||
|
|
@ -98,7 +93,7 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
break;
|
||||
}
|
||||
for (CardType t : token.getCardType()) {
|
||||
permanent.getCardType().add(t);
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
|
||||
// sub type
|
||||
|
|
@ -167,9 +162,9 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.PTChangingEffects_7
|
||||
|| layer == Layer.AbilityAddingRemovingEffects_6
|
||||
|| layer == Layer.ColorChangingEffects_5
|
||||
return layer == Layer.PTChangingEffects_7
|
||||
|| layer == Layer.AbilityAddingRemovingEffects_6
|
||||
|| layer == Layer.ColorChangingEffects_5
|
||||
|| layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@ import mage.MageObjectReference;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
|
@ -101,10 +97,9 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
for (String superType : token.getSupertype()) {
|
||||
if (!permanentAttachedTo.getSupertype().contains(superType)) {
|
||||
permanentAttachedTo.getSupertype().add(superType);
|
||||
}
|
||||
for (SuperType superType : token.getSuperType()) {
|
||||
permanentAttachedTo.addSuperType(superType);
|
||||
|
||||
}
|
||||
// card type
|
||||
switch (loseType) {
|
||||
|
|
@ -114,7 +109,7 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co
|
|||
break;
|
||||
}
|
||||
for (CardType cardType : token.getCardType()) {
|
||||
permanentAttachedTo.getCardType().add(cardType);
|
||||
permanentAttachedTo.addCardType(cardType);
|
||||
}
|
||||
|
||||
// sub type
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* Created by IGOUDT on 5-4-2017.
|
||||
*/
|
||||
public class BecomesCreatureIfVehicleEffect extends ContinuousEffectImpl {
|
||||
|
||||
private CardType addedType = CardType.CREATURE;
|
||||
|
||||
public BecomesCreatureIfVehicleEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||
this.staticText = "As long as enchanted permanent is a Vehicle, it's a creature in addition to its other types";
|
||||
}
|
||||
|
||||
public BecomesCreatureIfVehicleEffect(final BecomesCreatureIfVehicleEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent aura = game.getPermanent(source.getSourceId());
|
||||
if (aura != null && aura.getAttachedTo() != null) {
|
||||
Permanent enchanted = game.getPermanent(aura.getAttachedTo());
|
||||
if (enchanted != null && enchanted.getSubtype(game).contains("Vehicle")) {
|
||||
enchanted.addCardType(addedType);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesCreatureIfVehicleEffect copy() {
|
||||
return new BecomesCreatureIfVehicleEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,6 @@ import mage.game.permanent.Permanent;
|
|||
import mage.game.permanent.token.Token;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements SourceEffect {
|
||||
|
|
@ -113,12 +112,8 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
if (losePreviousTypes) {
|
||||
permanent.getCardType().clear();
|
||||
}
|
||||
if (!token.getCardType().isEmpty()) {
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.getCardType().add(t);
|
||||
}
|
||||
}
|
||||
for (CardType t : token.getCardType()) {
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
if (type != null && type.isEmpty() || type == null && permanent.isLand()) {
|
||||
permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes());
|
||||
|
|
@ -137,11 +132,10 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
break;
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (!token.getAbilities().isEmpty()) {
|
||||
for (Ability ability : token.getAbilities()) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
for (Ability ability : token.getAbilities()) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case PTChangingEffects_7:
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
|
|||
if (!token.getCardType().isEmpty()) {
|
||||
for (CardType t : token.getCardType()) {
|
||||
if (!permanent.getCardType().contains(t)) {
|
||||
permanent.getCardType().add(t);
|
||||
permanent.addCardType(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,9 +107,9 @@ public class BecomesFaceDownCreatureAllEffect extends ContinuousEffectImpl imple
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
permanent.setName("");
|
||||
permanent.getSupertype().clear();
|
||||
permanent.getSuperType().clear();
|
||||
permanent.getCardType().clear();
|
||||
permanent.getCardType().add(CardType.CREATURE);
|
||||
permanent.addCardType(CardType.CREATURE);
|
||||
permanent.getSubtype(game).clear();
|
||||
permanent.getManaCost().clear();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -163,9 +163,9 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
|
|||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
permanent.setName("");
|
||||
permanent.getSupertype().clear();
|
||||
permanent.getSuperType().clear();
|
||||
permanent.getCardType().clear();
|
||||
permanent.getCardType().add(CardType.CREATURE);
|
||||
permanent.addCardType(CardType.CREATURE);
|
||||
permanent.getSubtype(game).clear();
|
||||
break;
|
||||
case ColorChangingEffects_5:
|
||||
|
|
|
|||
|
|
@ -1,40 +1,102 @@
|
|||
/*
|
||||
* 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.
|
||||
* 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.continuous;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.CompoundAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class LoseAbilityAllEffect extends ContinuousEffectImpl {
|
||||
|
||||
protected final FilterPermanent filter;
|
||||
protected final Ability ability;
|
||||
protected CompoundAbility ability;
|
||||
protected boolean excludeSource;
|
||||
protected FilterPermanent filter;
|
||||
|
||||
public LoseAbilityAllEffect(FilterPermanent filter, Ability ability, Duration duration) {
|
||||
public LoseAbilityAllEffect(Ability ability, Duration duration) {
|
||||
this(ability, duration, new FilterPermanent("permanents"));
|
||||
}
|
||||
|
||||
public LoseAbilityAllEffect(CompoundAbility ability, Duration duration) {
|
||||
this(ability, duration, new FilterPermanent("permanents"));
|
||||
}
|
||||
|
||||
public LoseAbilityAllEffect(Ability ability, Duration duration, FilterPermanent filter) {
|
||||
this(ability, duration, filter, false);
|
||||
}
|
||||
|
||||
public LoseAbilityAllEffect(CompoundAbility ability, Duration duration, FilterPermanent filter) {
|
||||
this(ability, duration, filter, false);
|
||||
}
|
||||
|
||||
public LoseAbilityAllEffect(Ability ability, Duration duration, FilterPermanent filter, boolean excludeSource) {
|
||||
this(new CompoundAbility(ability), duration, filter, excludeSource);
|
||||
}
|
||||
|
||||
public LoseAbilityAllEffect(CompoundAbility ability, Duration duration, FilterPermanent filter, boolean excludeSource) {
|
||||
super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
this.filter = filter;
|
||||
this.ability = ability;
|
||||
staticText = filter.getMessage() + " lose " + ability.toString() + (duration.toString().isEmpty() ? "" : ' ' + duration.toString());
|
||||
this.filter = filter;
|
||||
this.excludeSource = excludeSource;
|
||||
}
|
||||
|
||||
public LoseAbilityAllEffect(final LoseAbilityAllEffect effect) {
|
||||
super(effect);
|
||||
this.ability = effect.ability.copy();
|
||||
this.filter = effect.filter.copy();
|
||||
this.ability = effect.ability;
|
||||
this.excludeSource = effect.excludeSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -44,10 +106,40 @@ public class LoseAbilityAllEffect extends ContinuousEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (permanent != null) {
|
||||
while (permanent.getAbilities().contains(ability)) {
|
||||
permanent.getAbilities().remove(ability);
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Iterator<MageObjectReference> it = affectedObjectList.iterator(); it.hasNext();) { // filter may not be used again, because object can have changed filter relevant attributes but still geets boost
|
||||
Permanent perm = it.next().getPermanentOrLKIBattlefield(game); //LKI is neccessary for "dies triggered abilities" to work given to permanets (e.g. Showstopper)
|
||||
if (perm != null) {
|
||||
for (Ability ability : ability) {
|
||||
perm.getAbilities().removeIf(entry -> entry.getId().equals(ability.getId()));
|
||||
}
|
||||
} else {
|
||||
it.remove();
|
||||
if (affectedObjectList.isEmpty()) {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
for (Ability ability : ability) {
|
||||
perm.getAbilities().removeIf(entry -> entry.getId().equals(ability.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// still as long as the prev. permanent is known to the LKI (e.g. Mikaeus, the Unhallowed) so gained dies triggered ability will trigger
|
||||
HashMap<UUID, MageObject> LKIBattlefield = game.getLKI().get(Zone.BATTLEFIELD);
|
||||
if (LKIBattlefield != null) {
|
||||
for (MageObject mageObject : LKIBattlefield.values()) {
|
||||
Permanent perm = (Permanent) mageObject;
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
if (filter.match(perm, source.getSourceId(), source.getControllerId(), game)) {
|
||||
for (Ability ability : ability) {
|
||||
perm.getAbilities().removeIf(entry -> entry.getId().equals(ability.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
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 LevelX2
|
||||
*/
|
||||
public class SetPowerToughnessEnchantedEffect extends ContinuousEffectImpl {
|
||||
|
||||
public SetPowerToughnessEnchantedEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.SetPT_7b, Outcome.BoostCreature);
|
||||
staticText = "Enchanted creature has base power and toughness 0/2";
|
||||
}
|
||||
|
||||
public SetPowerToughnessEnchantedEffect(final SetPowerToughnessEnchantedEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetPowerToughnessEnchantedEffect copy() {
|
||||
return new SetPowerToughnessEnchantedEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if (enchantment != null && enchantment.getAttachedTo() != null) {
|
||||
Permanent enchanted = game.getPermanent(enchantment.getAttachedTo());
|
||||
if (enchanted != null) {
|
||||
enchanted.getPower().setValue(0);
|
||||
enchanted.getToughness().setValue(2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -29,10 +29,10 @@
|
|||
package mage.abilities.effects.common.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
|
||||
import mage.game.Game;
|
||||
|
|
@ -58,7 +58,7 @@ public class CastWithoutPayingManaCostEffect extends OneShotEffect {
|
|||
public CastWithoutPayingManaCostEffect(int maxCost) {
|
||||
super(Outcome.PlayForFree);
|
||||
filter = new FilterNonlandCard("card with converted mana cost " + maxCost + " or less from your hand");
|
||||
filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, maxCost + 1));
|
||||
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, maxCost + 1));
|
||||
this.manaCost = maxCost;
|
||||
this.staticText = "you may cast a card with converted mana cost " + maxCost + " or less from your hand without paying its mana cost";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.cost;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CostModificationType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class SourceCostReductionForEachCardInGraveyardEffect extends CostModificationEffectImpl {
|
||||
|
||||
private FilterCard filter;
|
||||
|
||||
public SourceCostReductionForEachCardInGraveyardEffect() {
|
||||
this(new FilterCard());
|
||||
}
|
||||
|
||||
public SourceCostReductionForEachCardInGraveyardEffect(FilterCard filter) {
|
||||
super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
|
||||
this.filter = filter;
|
||||
staticText = "{this} costs {1} less to cast for each " + filter.getMessage() + " in your graveyard";
|
||||
}
|
||||
|
||||
SourceCostReductionForEachCardInGraveyardEffect(SourceCostReductionForEachCardInGraveyardEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
int reductionAmount = player.getGraveyard().count(filter, game);
|
||||
CardUtil.reduceCost(abilityToModify, reductionAmount);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) {
|
||||
return game.getCard(abilityToModify.getSourceId()) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceCostReductionForEachCardInGraveyardEffect copy() {
|
||||
return new SourceCostReductionForEachCardInGraveyardEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
*/
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
|
|
@ -103,7 +105,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
countersToAdd--;
|
||||
}
|
||||
newCounter.add(countersToAdd);
|
||||
card.addCounters(newCounter, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
card.addCounters(newCounter, source, game, appliedEffects);
|
||||
if (informPlayers && !game.isSimulation()) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
|
|
@ -128,7 +131,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
}
|
||||
newCounter.add(countersToAdd);
|
||||
int before = permanent.getCounters(game).getCount(newCounter.getName());
|
||||
permanent.addCounters(newCounter, source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
|
||||
permanent.addCounters(newCounter, source, game, appliedEffects); // if used from a replacement effect, the basic event determines if an effect was already applied to an event
|
||||
if (informPlayers && !game.isSimulation()) {
|
||||
int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before;
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
|
|
@ -150,12 +154,10 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
sb.append("put ");
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
|
||||
} else if (amount.toString().equals("X") && amount.getMessage().isEmpty()) {
|
||||
sb.append("X ");
|
||||
} else {
|
||||
if (amount.toString().equals("X") && amount.getMessage().isEmpty()) {
|
||||
sb.append("X ");
|
||||
} else {
|
||||
sb.append("a ");
|
||||
}
|
||||
sb.append("a ");
|
||||
}
|
||||
sb.append(counter.getName().toLowerCase()).append(" counter on {this}");
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -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.replacement;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CreateTwiceThatManyTokensEffect extends ReplacementEffectImpl {
|
||||
|
||||
public CreateTwiceThatManyTokensEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Copy);
|
||||
staticText = "If an effect would create one or more tokens under your control, it creates twice that many of those tokens instead";
|
||||
}
|
||||
|
||||
public CreateTwiceThatManyTokensEffect(final CreateTwiceThatManyTokensEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateTwiceThatManyTokensEffect copy() {
|
||||
return new CreateTwiceThatManyTokensEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CREATE_TOKEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return event.getPlayerId().equals(source.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
event.setAmount(event.getAmount() * 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,113 +1,114 @@
|
|||
/*
|
||||
* 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().isEmpty()) {
|
||||
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().isEmpty()) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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. " + (forceToSearchBoth ? "Then shuffle your library" : "If you search your library this way, shuffle it");
|
||||
}
|
||||
|
||||
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().isEmpty()) {
|
||||
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().isEmpty()) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@
|
|||
package mage.abilities.effects.common.search;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
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;
|
||||
|
|
@ -67,7 +67,7 @@ public class SearchLibraryWithLessCMCPutInPlayEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
FilterCard advancedFilter = filter.copy(); // never change static objects so copy the object here before
|
||||
advancedFilter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, source.getManaCostsToPay().getX() + 1));
|
||||
advancedFilter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, source.getManaCostsToPay().getX() + 1));
|
||||
TargetCardInLibrary target = new TargetCardInLibrary(advancedFilter);
|
||||
if (controller.searchLibrary(target, game)) {
|
||||
if (!target.getTargets().isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
package mage.abilities.effects.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
|
@ -35,7 +36,6 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
|
|
@ -96,7 +96,7 @@ public class BolsterEffect extends OneShotEffect {
|
|||
if (leastToughness != Integer.MAX_VALUE) {
|
||||
if (selectedCreature == null) {
|
||||
FilterPermanent filter = new FilterControlledCreaturePermanent("creature you control with toughness " + leastToughness);
|
||||
filter.add(new ToughnessPredicate(Filter.ComparisonType.Equal, leastToughness));
|
||||
filter.add(new ToughnessPredicate(ComparisonType.EQUAL_TO, leastToughness));
|
||||
Target target = new TargetPermanent(1,1, filter, true);
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
selectedCreature = game.getPermanent(target.getFirstTarget());
|
||||
|
|
|
|||
227
Mage/src/main/java/mage/abilities/keyword/AftermathAbility.java
Normal file
227
Mage/src/main/java/mage/abilities/keyword/AftermathAbility.java
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Copyright 2011 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.keyword;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.*;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCardHalf;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
* Aftermath
|
||||
*
|
||||
* TODO: Implement once we get details on the comprehensive rules meaning of the
|
||||
* ability
|
||||
*
|
||||
* Current text is a shell copied from Flashback
|
||||
*
|
||||
* @author stravant
|
||||
*/
|
||||
public class AftermathAbility extends SimpleStaticAbility {
|
||||
|
||||
public AftermathAbility() {
|
||||
super(Zone.ALL, new AftermathCastFromGraveyard());
|
||||
addEffect(new AftermathCantCastFromHand());
|
||||
addEffect(new AftermathExileAsResolvesFromGraveyard());
|
||||
}
|
||||
|
||||
public AftermathAbility(final AftermathAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AftermathAbility copy() {
|
||||
return new AftermathAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule(boolean all) {
|
||||
if (all) {
|
||||
return "Aftermath <i>(Cast this card only from your graveyard. Exile it afterwards.)</i>";
|
||||
} else {
|
||||
return "Aftermath";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AftermathCastFromGraveyard extends AsThoughEffectImpl {
|
||||
|
||||
public AftermathCastFromGraveyard() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit);
|
||||
staticText = "Cast {this} from your graveyard";
|
||||
}
|
||||
|
||||
public AftermathCastFromGraveyard(final AftermathCastFromGraveyard effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AftermathCastFromGraveyard copy() {
|
||||
return new AftermathCastFromGraveyard(this);
|
||||
}
|
||||
|
||||
private static String msb(UUID id) {
|
||||
return Integer.toUnsignedString((int) id.getMostSignificantBits(), 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (objectId.equals(source.getSourceId())
|
||||
& affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class AftermathCantCastFromHand extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public AftermathCantCastFromHand() {
|
||||
super(Duration.EndOfGame, Outcome.Detriment);
|
||||
staticText = ", but not from anywhere else";
|
||||
}
|
||||
|
||||
public AftermathCantCastFromHand(final AftermathCantCastFromHand effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AftermathCantCastFromHand copy() {
|
||||
return new AftermathCantCastFromHand(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Card card = game.getCard(event.getSourceId());
|
||||
if (card != null && card.getId().equals(source.getSourceId())) {
|
||||
Zone zone = game.getState().getZone(card.getId());
|
||||
if (zone != null && (zone != Zone.GRAVEYARD)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
|
||||
|
||||
AftermathExileAsResolvesFromGraveyard() {
|
||||
super(Duration.WhileOnStack, Outcome.Detriment);
|
||||
this.staticText = "Exile it afterwards.";
|
||||
}
|
||||
|
||||
AftermathExileAsResolvesFromGraveyard(AftermathExileAsResolvesFromGraveyard effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent evt, Ability source, Game game) {
|
||||
ZoneChangeEvent event = (ZoneChangeEvent) evt;
|
||||
if (event.getFromZone() == Zone.STACK && event.getToZone() != Zone.EXILED) {
|
||||
// Moving something from stack to somewhere else
|
||||
|
||||
// Get the source id, getting the whole split card's ID, because
|
||||
// that's the card that is changing zones in the event, but
|
||||
// source.getSourceId is only the split card half.
|
||||
// If branch so that we also support putting Aftermath on
|
||||
// non-split cards for... whatever reason, in case somebody
|
||||
// wants to do that in the future.
|
||||
UUID sourceId = source.getSourceId();
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (sourceCard != null && sourceCard instanceof SplitCardHalf) {
|
||||
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
|
||||
sourceId = sourceCard.getId();
|
||||
}
|
||||
|
||||
if (event.getTargetId() == sourceId) {
|
||||
// Moving this spell from stack to yard
|
||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||
if (spell != null && spell.getFromZone() == Zone.GRAVEYARD) {
|
||||
// And this spell was cast from the graveyard, so we need to exile it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
UUID sourceId = source.getSourceId();
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (sourceCard != null && sourceCard instanceof SplitCardHalf) {
|
||||
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
|
||||
sourceId = sourceCard.getId();
|
||||
}
|
||||
|
||||
if (sourceCard != null) {
|
||||
Player player = game.getPlayer(sourceCard.getOwnerId());
|
||||
if (player != null) {
|
||||
return player.moveCardToExileWithInfo(sourceCard, null, "", sourceId, game, ((ZoneChangeEvent) event).getFromZone(), true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AftermathExileAsResolvesFromGraveyard copy() {
|
||||
return new AftermathExileAsResolvesFromGraveyard(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -151,12 +151,12 @@ public class BestowAbility extends SpellAbility {
|
|||
if (basicObject != null) {
|
||||
basicObject.getSubtype(null).remove("Aura");
|
||||
if (!basicObject.isCreature()) {
|
||||
basicObject.getCardType().add(CardType.CREATURE);
|
||||
basicObject.addCardType(CardType.CREATURE);
|
||||
}
|
||||
}
|
||||
permanent.getSubtype(null).remove("Aura");
|
||||
if (!permanent.isCreature()) {
|
||||
permanent.getCardType().add(CardType.CREATURE);
|
||||
permanent.addCardType(CardType.CREATURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -71,7 +73,8 @@ class BloodthirstEffect extends OneShotEffect {
|
|||
if (watcher != null && watcher.conditionMet()) {
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game);
|
||||
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game, appliedEffects);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -20,25 +20,29 @@
|
|||
* 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.keyword;
|
||||
|
||||
import mage.constants.Zone;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.DiscardSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.CostEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.target.Targets;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -47,16 +51,16 @@ public class CyclingAbility extends ActivatedAbilityImpl {
|
|||
|
||||
private final Cost cost;
|
||||
private final String text;
|
||||
|
||||
|
||||
public CyclingAbility(Cost cost) {
|
||||
super(Zone.HAND, new DrawCardSourceControllerEffect(1), cost);
|
||||
super(Zone.HAND, new DrawCardSourceControllerEffect(1), new CyclingCost(cost));
|
||||
this.addCost(new DiscardSourceCost());
|
||||
this.cost = cost;
|
||||
this.text = "Cycling";
|
||||
}
|
||||
|
||||
public CyclingAbility(Cost cost, FilterCard filter, String text){
|
||||
super(Zone.HAND, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true), cost);
|
||||
|
||||
public CyclingAbility(Cost cost, FilterCard filter, String text) {
|
||||
super(Zone.HAND, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true), new CyclingCost(cost));
|
||||
this.addCost(new DiscardSourceCost());
|
||||
this.cost = cost;
|
||||
this.text = text;
|
||||
|
|
@ -76,14 +80,87 @@ public class CyclingAbility extends ActivatedAbilityImpl {
|
|||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder rule = new StringBuilder(this.text);
|
||||
if(cost instanceof ManaCost){
|
||||
if (cost instanceof ManaCost) {
|
||||
rule.append(' ');
|
||||
}
|
||||
else{
|
||||
rule.append("—");
|
||||
} else {
|
||||
rule.append("—");
|
||||
}
|
||||
rule.append(cost.getText()).append(" <i>(").append(super.getRule(true)).append(")</i>");
|
||||
return rule.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CyclingCost implements Cost {
|
||||
|
||||
protected Cost cost;
|
||||
|
||||
public CyclingCost(Cost cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
public CyclingCost(final CyclingCost cost) {
|
||||
this.cost = cost.cost.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
|
||||
return pay(ability, game, sourceId, controllerId, noMana, cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
CostEvent costEvent = new CostEvent(GameEvent.EventType.CAN_PAY_CYCLE_COST, sourceId, sourceId, controllerId, cost);
|
||||
game.replaceEvent(costEvent);
|
||||
return cost.canPay(ability, sourceId, controllerId, game) || costEvent.getCost().canPay(ability, sourceId, controllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
CostEvent costEvent = new CostEvent(GameEvent.EventType.PAY_CYCLE_COST, sourceId, sourceId, controllerId, cost);
|
||||
game.replaceEvent(costEvent);
|
||||
cost = costEvent.getCost();
|
||||
return cost.pay(ability, game, sourceId, controllerId, noMana, cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return cost.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
cost.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Targets getTargets() {
|
||||
return cost.getTargets();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPaid() {
|
||||
return cost.isPaid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearPaid() {
|
||||
cost.clearPaid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaid() {
|
||||
cost.setPaid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return cost.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cost copy() {
|
||||
return new CyclingCost(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
126
Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java
Normal file
126
Mage/src/main/java/mage/abilities/keyword/EmbalmAbility.java
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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.keyword;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.ExileSourceFromGraveCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.token.EmptyToken;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EmbalmAbility extends ActivatedAbilityImpl {
|
||||
|
||||
private String rule;
|
||||
|
||||
public EmbalmAbility(Cost cost, Card card) {
|
||||
super(Zone.GRAVEYARD, new EmbalmEffect(), cost);
|
||||
addCost(new ExileSourceFromGraveCost());
|
||||
this.rule = setRule(cost, card);
|
||||
this.timing = TimingRule.SORCERY;
|
||||
setRule(cost, card);
|
||||
}
|
||||
|
||||
public EmbalmAbility(final EmbalmAbility ability) {
|
||||
super(ability);
|
||||
this.rule = ability.rule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbalmAbility copy() {
|
||||
return new EmbalmAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
private String setRule(Cost cost, Card card) {
|
||||
StringBuilder sb = new StringBuilder("Embalm ").append(cost.getText());
|
||||
sb.append(" <i>(").append(cost.getText());
|
||||
sb.append(", Exile this card from your graveyard: Create a token that's a copy of it, except it's a white Zombie ");
|
||||
for (String subtype : card.getSubtype(null)) {
|
||||
sb.append(subtype).append(" ");
|
||||
}
|
||||
sb.append(" with no mana cost. Embalm only as a sorcery.)</i>");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class EmbalmEffect extends OneShotEffect {
|
||||
|
||||
public EmbalmEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
}
|
||||
|
||||
public EmbalmEffect(final EmbalmEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbalmEffect copy() {
|
||||
return new EmbalmEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null && card != null) {
|
||||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(card); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
|
||||
token.getColor(game).setColor(ObjectColor.WHITE);
|
||||
if (!token.getSubtype(game).contains("Zombie")) {
|
||||
token.getSubtype(game).add(0, "Zombie");
|
||||
}
|
||||
token.getManaCost().clear();
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source.getSourceId(), controller.getId()));
|
||||
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), false, false, null);
|
||||
// Probably it makes sense to remove also the Embalm ability (it's not shown on the token cards).
|
||||
// Also it can never get active or? But it's not mentioned in the reminder text.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
206
Mage/src/main/java/mage/abilities/keyword/ExertAbility.java
Normal file
206
Mage/src/main/java/mage/abilities/keyword/ExertAbility.java
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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.keyword;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.common.BecomesExertSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.WatcherScope;
|
||||
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.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ExertAbility extends SimpleStaticAbility {
|
||||
|
||||
private String ruleText;
|
||||
|
||||
public ExertAbility(BecomesExertSourceTriggeredAbility ability) {
|
||||
this(ability, false);
|
||||
}
|
||||
|
||||
public ExertAbility(BecomesExertSourceTriggeredAbility ability, boolean exertOnlyOncePerTurn) {
|
||||
super(Zone.BATTLEFIELD, new ExertReplacementEffect(exertOnlyOncePerTurn));
|
||||
ruleText = (exertOnlyOncePerTurn
|
||||
? "If {this} hasn't been exerted this turn, you may exert it"
|
||||
: "You may exert {this}") + " as it attacks. ";
|
||||
if (ability != null) {
|
||||
this.addSubAbility(ability);
|
||||
ruleText += ("When you do,");
|
||||
ability.getEffects().stream().forEach((effect) -> {
|
||||
ruleText += " " + effect.getText(ability.getModes().getMode());
|
||||
});
|
||||
ruleText += ". ";
|
||||
ability.setRuleVisible(false);
|
||||
}
|
||||
ruleText += "<i>(An exterted creature can't untap during your next untap step)</i>";
|
||||
if (exertOnlyOncePerTurn) {
|
||||
getWatchers().add(new ExertedThisTurnWatcher());
|
||||
}
|
||||
}
|
||||
|
||||
public ExertAbility(final ExertAbility ability) {
|
||||
super(ability);
|
||||
this.ruleText = ability.ruleText;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExertAbility copy() {
|
||||
return new ExertAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return ruleText;
|
||||
}
|
||||
}
|
||||
|
||||
class ExertReplacementEffect extends ReplacementEffectImpl {
|
||||
|
||||
final private boolean exertOnlyOncePerTurn;
|
||||
|
||||
public ExertReplacementEffect(boolean exertOnlyOncePerTurn) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
staticText = "You may exert {this} as it attacks";
|
||||
this.exertOnlyOncePerTurn = exertOnlyOncePerTurn;
|
||||
}
|
||||
|
||||
public ExertReplacementEffect(ExertReplacementEffect effect) {
|
||||
super(effect);
|
||||
this.exertOnlyOncePerTurn = effect.exertOnlyOncePerTurn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.ATTACKER_DECLARED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
return event.getSourceId().equals(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Permanent creature = game.getPermanent(event.getSourceId());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (creature != null && controller != null) {
|
||||
if (exertOnlyOncePerTurn) {
|
||||
MageObjectReference creatureReference = new MageObjectReference(creature.getId(), creature.getZoneChangeCounter(game), game);
|
||||
ExertedThisTurnWatcher watcher = (ExertedThisTurnWatcher) game.getState().getWatchers().get(ExertedThisTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getExertedThisTurnCreatures().contains(creatureReference)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (controller.chooseUse(outcome, "Exert " + creature.getLogName() + '?',
|
||||
"An exterted creature can't untap during your next untap step.", "Yes", "No", source, game)) {
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(controller.getLogName() + " exerted " + creature.getName());
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_EXERTED, creature.getId(), creature.getId(), creature.getControllerId()));
|
||||
ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(creature, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
return staticText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExertReplacementEffect copy() {
|
||||
return new ExertReplacementEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ExertedThisTurnWatcher extends Watcher {
|
||||
|
||||
private final Set<MageObjectReference> exertedThisTurnCreatures;
|
||||
|
||||
public ExertedThisTurnWatcher() {
|
||||
super(ExertedThisTurnWatcher.class.getName(), WatcherScope.GAME);
|
||||
exertedThisTurnCreatures = new HashSet<>();
|
||||
}
|
||||
|
||||
public ExertedThisTurnWatcher(final ExertedThisTurnWatcher watcher) {
|
||||
super(watcher);
|
||||
exertedThisTurnCreatures = new HashSet<>(watcher.exertedThisTurnCreatures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Watcher copy() {
|
||||
return new ExertedThisTurnWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.BECOMES_EXERTED) {
|
||||
this.exertedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game));
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MageObjectReference> getExertedThisTurnCreatures() {
|
||||
return this.exertedThisTurnCreatures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
exertedThisTurnCreatures.clear();
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue