Fixing issues with Changelings and general problems with creature types (ready to merge) (#7098)

* updated Changelings to use setIsAllCreatureTypes

* updated Dr Julius Jumblemorph and Mistform Ultimus to not use changeling

* added test for Mistform Ultimus

* updated effects which give all creature types to controlled creatures

* updated effects which give all creature types to targeted creatures

* Update LoseAllCreatureTypesTargetEffect.java

* updated effects which give all creature types to attached creatures

* Update EgoErasure.java

* added another test for changelings

* updated two tokens I left out before

* updated hasSubtype

* updated shareCreatureTypes

* fixed an incorrect test

* cleaned up some cards which check for shared creature types

* added new changeling test

* fixed issue with shareCreatureTypes

* fixed a text issue

* added new tests for subtype effects

* various individual card fixes and cleanups

* fixed and updated various effects

* many more fixes

* a few more fixes

* added test for One with the Stars

* added changeling verify test

* updated effects which add additional subtypes

* more miscellaneous fixes

* added additional test

* some fixes for card type checks

* updated methods for adding types to make it easier to avoid duplicates and illegal additions

* small test update

* fixed a recursive loop issue

* fixed another error

* fixed it for real this time

* streamlined type removal process

* streamlined subtype set generation
This commit is contained in:
Evan Kranzler 2020-10-30 22:32:59 -04:00 committed by GitHub
parent 42e00b7a37
commit 8617bc128e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
182 changed files with 2431 additions and 2820 deletions

View file

@ -1,25 +1,25 @@
package mage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
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.abilities.text.TextPart;
import mage.cards.Card;
import mage.cards.FrameStyle;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SubTypeSet;
import mage.constants.SuperType;
import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import mage.util.SubTypeList;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public interface MageObject extends MageItem, Serializable {
String getName();
@ -126,6 +126,10 @@ public interface MageObject extends MageItem, Serializable {
return getCardType().contains(CardType.PLANESWALKER);
}
default boolean isTribal() {
return getCardType().contains(CardType.TRIBAL);
}
default boolean isPermanent() {
return isCreature() || isArtifact() || isPlaneswalker() || isEnchantment() || isLand();
}
@ -139,6 +143,9 @@ public interface MageObject extends MageItem, Serializable {
}
default void addSuperType(SuperType superType) {
if (getSuperType().contains(superType)) {
return;
}
getSuperType().add(superType);
}
@ -151,9 +158,31 @@ public interface MageObject extends MageItem, Serializable {
}
default void addCardType(CardType cardType) {
if (getCardType().contains(cardType)) {
return;
}
getCardType().add(cardType);
}
default void addSubType(Game game, SubType... subTypes) {
for (SubType subType : subTypes) {
if (subType.canGain(this)
&& !hasSubtype(subType, game)) {
getSubtype(game).add(subType);
}
}
}
default void removeAllSubTypes(Game game) {
getSubtype(game).clear();
setIsAllCreatureTypes(false);
}
default void removeAllCreatureTypes(Game game) {
getSubtype(game).removeAll(SubType.getCreatureTypes());
setIsAllCreatureTypes(false);
}
/**
* Checks whether two cards share card types.
*
@ -180,27 +209,36 @@ public interface MageObject extends MageItem, Serializable {
return false;
}
default boolean shareSubtypes(Card otherCard, Game game) {
if (otherCard == null) {
throw new IllegalArgumentException("Params can't be null");
default boolean shareCreatureTypes(Card otherCard, Game game) {
if (!isCreature() && !isTribal()) {
return false;
}
if (this.isCreature() && otherCard.isCreature()) {
if (this.hasAbility(ChangelingAbility.getInstance(), game)
|| this.isAllCreatureTypes()
|| otherCard.hasAbility(ChangelingAbility.getInstance(), game)
|| otherCard.isAllCreatureTypes()) {
return true;
}
if (!otherCard.isCreature() && !otherCard.isTribal()) {
return false;
}
for (SubType subtype : this.getSubtype(game)) {
if (otherCard.hasSubtype(subtype, game)) {
return true;
}
boolean isAllA = this.isAllCreatureTypes();
boolean isAnyA = isAllA || this.getSubtype(game)
.stream()
.map(SubType::getSubTypeSet)
.anyMatch(SubTypeSet.CreatureType::equals);
boolean isAllB = otherCard.isAllCreatureTypes();
boolean isAnyB = isAllB || otherCard
.getSubtype(game)
.stream()
.map(SubType::getSubTypeSet)
.anyMatch(SubTypeSet.CreatureType::equals);
if (!isAnyA || !isAnyB) {
return false;
}
return false;
if (isAllA) {
return isAllB || isAnyB;
}
return isAnyA
&& (isAllB || this
.getSubtype(game)
.stream()
.filter(subType -> subType.getSubTypeSet() == SubTypeSet.CreatureType)
.anyMatch(subType -> otherCard.hasSubtype(subType, game)));
}
boolean isAllCreatureTypes();

View file

@ -1,7 +1,5 @@
package mage;
import java.util.*;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
@ -11,7 +9,6 @@ import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.keyword.ChangelingAbility;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.abilities.text.TextPart;
import mage.abilities.text.TextPartSubType;
@ -20,10 +17,11 @@ import mage.cards.mock.MockCard;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.util.GameLog;
import mage.util.SubTypeList;
import java.util.*;
public abstract class MageObjectImpl implements MageObject {
protected UUID objectId;
@ -230,25 +228,10 @@ public abstract class MageObjectImpl implements MageObject {
if (value == null) {
return false;
}
SubTypeList subtypes = this.getSubtype(game);
if (subtypes.contains(value)) {
if (value.getSubTypeSet() == SubTypeSet.CreatureType && isAllCreatureTypes()) {
return true;
} else {
// checking for Changeling
// first make sure input parameter is a creature subtype
// if not, then ChangelingAbility doesn't matter
if (value.getSubTypeSet() != SubTypeSet.CreatureType) {
return false;
}
// as it is a creature subtype, then check the existence of Changeling
Abilities<Ability> checkList;
if (this instanceof Permanent) {
checkList = ((Permanent) this).getAbilities(game);
} else {
checkList = abilities;
}
return checkList.contains(ChangelingAbility.getInstance()) || isAllCreatureTypes();
}
return getSubtype(game).contains(value);
}
@Override
@ -289,7 +272,7 @@ public abstract class MageObjectImpl implements MageObject {
@Override
public void setIsAllCreatureTypes(boolean value) {
isAllCreatureTypes = value;
isAllCreatureTypes = value && (this.isTribal() || this.isCreature());
}
@Override

View file

@ -96,7 +96,7 @@ class KinshipBaseEffect extends OneShotEffect {
if (card != null) {
Cards cards = new CardsImpl(card);
controller.lookAtCards(sourcePermanent.getName(), cards, game);
if (sourcePermanent.shareSubtypes(card, game)) {
if (sourcePermanent.shareCreatureTypes(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) {

View file

@ -7,10 +7,7 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import static mage.constants.CardType.CREATURE;
/**
*
* @author htrajan
*/
public class AttachedToCreatureSourceTriggeredAbility extends TriggeredAbilityImpl {
@ -33,7 +30,7 @@ public class AttachedToCreatureSourceTriggeredAbility extends TriggeredAbilityIm
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent attachedPermanent = game.getPermanent(event.getTargetId());
return attachedPermanent != null && attachedPermanent.getCardType().contains(CREATURE);
return attachedPermanent != null && attachedPermanent.isCreature();
}
@Override

View file

@ -1,8 +1,5 @@
package mage.abilities.common;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.SpecialAction;
@ -15,22 +12,18 @@ import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CreateSpecialActionEffect;
import mage.abilities.effects.common.RemoveSpecialActionEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author emerald000
*/
public class LicidAbility extends ActivatedAbilityImpl {
@ -116,8 +109,8 @@ class LicidContinuousEffect extends ContinuousEffectImpl {
case TypeChangingEffects_4:
licid.getCardType().clear();
licid.addCardType(CardType.ENCHANTMENT);
licid.getSubtype(game).clear();
licid.getSubtype(game).add(SubType.AURA);
licid.removeAllSubTypes(game);
licid.addSubType(game, SubType.AURA);
break;
case AbilityAddingRemovingEffects_6:
List<Ability> toRemove = new ArrayList<>();

View file

@ -103,10 +103,11 @@ public class CopyEffect extends ContinuousEffectImpl {
for (CardType type : copyFromObject.getCardType()) {
permanent.addCardType(type);
}
permanent.getSubtype(game).clear();
for (SubType type : copyFromObject.getSubtype(game)) {
permanent.getSubtype(game).add(type);
}
permanent.removeAllSubTypes(game);
permanent.getSubtype(game).addAll(copyFromObject.getSubtype(game));
permanent.setIsAllCreatureTypes(copyFromObject.isAllCreatureTypes());
permanent.getSuperType().clear();
for (SuperType type : copyFromObject.getSuperType()) {
permanent.addSuperType(type);

View file

@ -31,10 +31,11 @@ public class CopyTokenEffect extends ContinuousEffectImpl {
for (CardType type : token.getCardType()) {
permanent.addCardType(type);
}
permanent.getSubtype(game).clear();
permanent.removeAllSubTypes(game);
for (SubType type : token.getSubtype(game)) {
permanent.getSubtype(game).add(type);
permanent.addSubType(game, type);
}
permanent.setIsAllCreatureTypes(token.isAllCreatureTypes());
permanent.getSuperType().clear();
for (SuperType type : token.getSuperType()) {
permanent.addSuperType(type);

View file

@ -1,10 +1,5 @@
package mage.abilities.effects.common;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
@ -25,6 +20,11 @@ import mage.util.CardUtil;
import mage.util.functions.ApplyToPermanent;
import mage.util.functions.EmptyApplyToPermanent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
* @author LevelX2
*/
@ -179,10 +179,10 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
token.getSuperType().remove(SuperType.LEGENDARY);
}
if (startingLoyalty!=-1){
if (startingLoyalty != -1) {
token.setStartingLoyalty(startingLoyalty);
}
if (additionalCardType != null && !token.getCardType().contains(additionalCardType)) {
if (additionalCardType != null) {
token.addCardType(additionalCardType);
}
if (hasHaste) {
@ -199,12 +199,12 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
token.removePTCDA();
token.getToughness().modifyBaseValue(tokenToughness);
}
if (additionalSubType != null && !token.hasSubtype(additionalSubType, game)) {
token.getSubtype(game).add(additionalSubType);
if (onlySubType != null) {
token.removeAllCreatureTypes(game);
token.addSubType(game, onlySubType);
}
if (onlySubType != null && !token.hasSubtype(onlySubType, game)) {
token.getSubtype(game).clear();
token.getSubtype(game).add(onlySubType);
if (additionalSubType != null && !token.hasSubtype(additionalSubType, game)) {
token.addSubType(game, additionalSubType);
}
if (color != null) {
token.getColor(game).setColor(color);

View file

@ -29,9 +29,7 @@ public class AddCardSubTypeTargetEffect extends ContinuousEffectImpl {
public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(targetPointer.getFirst(game, source));
if (target != null) {
if (!target.hasSubtype(addedSubType, game)) {
target.getSubtype(game).add(addedSubType);
}
target.addSubType(game, addedSubType);
} else {
if (duration == Duration.Custom) {
discard();

View file

@ -35,8 +35,8 @@ public class AddCardSubtypeAllEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
if (perm != null && !perm.hasSubtype(addedSubtype, game)) {
perm.getSubtype(game).add(addedSubtype);
if (perm != null) {
perm.addSubType(game, addedSubtype);
}
}
return true;

View file

@ -33,8 +33,8 @@ public class AddCardSubtypeAttachedEffect extends ContinuousEffectImpl {
Permanent equipment = game.getPermanent(source.getSourceId());
if (equipment != null && equipment.getAttachedTo() != null) {
Permanent target = game.getPermanent(equipment.getAttachedTo());
if (target != null && !target.hasSubtype(addedSubtype, game))
target.getSubtype(game).add(addedSubtype);
if (target != null)
target.addSubType(game, addedSubtype);
}
return true;
}

View file

@ -33,7 +33,7 @@ public class AddCardTypeAttachedEffect extends ContinuousEffectImpl {
Permanent equipment = game.getPermanent(source.getSourceId());
if (equipment != null && equipment.getAttachedTo() != null) {
Permanent target = game.getPermanent(equipment.getAttachedTo());
if (target != null && !target.getCardType().contains(addedCardType)) {
if (target != null) {
target.addCardType(addedCardType);
}
}

View file

@ -1,8 +1,5 @@
package mage.abilities.effects.common.continuous;
import java.util.ArrayList;
import java.util.Locale;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.Mode;
@ -11,6 +8,9 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.ArrayList;
import java.util.Locale;
/**
* @author emerald000
*/
@ -46,9 +46,7 @@ public class AddCardTypeSourceEffect extends ContinuousEffectImpl {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && affectedObjectList.contains(new MageObjectReference(permanent, game))) {
for (CardType cardType : addedCardTypes) {
if (!permanent.getCardType().contains(cardType)) {
permanent.addCardType(cardType);
}
permanent.addCardType(cardType);
}
return true;
} else if (this.getDuration() == Duration.Custom) {

View file

@ -1,20 +1,15 @@
package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.ArrayList;
import java.util.Locale;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.CardType;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* @author nantuko
@ -48,9 +43,7 @@ public class AddCardTypeTargetEffect extends ContinuousEffectImpl {
Permanent target = game.getPermanent(targetId);
if (target != null) {
for (CardType cardType : addedCardTypes) {
if (!target.getCardType().contains(cardType)) {
target.addCardType(cardType);
}
target.addCardType(cardType);
}
result = true;
}

View file

@ -23,8 +23,8 @@ public class AddChosenSubtypeEffect extends ContinuousEffectImpl {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(permanent.getId(), game);
if (subType != null && !permanent.hasSubtype(subType, game)) {
permanent.getSubtype(game).add(subType);
if (subType != null) {
permanent.addSubType(game, subType);
}
}
return true;

View file

@ -14,7 +14,7 @@ import mage.game.permanent.Permanent;
public class BecomesAllBasicsControlledEffect extends ContinuousEffectImpl {
public BecomesAllBasicsControlledEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
this.staticText = "Lands you control are every basic land type in addition to their other types";
dependencyTypes.add(DependencyType.BecomeMountain);
dependencyTypes.add(DependencyType.BecomeForest);
@ -27,65 +27,29 @@ public class BecomesAllBasicsControlledEffect extends ContinuousEffectImpl {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public BecomesAllBasicsControlledEffect copy() {
return new BecomesAllBasicsControlledEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game)) {
switch (layer) {
case TypeChangingEffects_4:
if (!permanent.hasSubtype(SubType.SWAMP, game)) {
permanent.getSubtype(game).add(SubType.SWAMP);
}
if (!permanent.hasSubtype(SubType.MOUNTAIN, game)) {
permanent.getSubtype(game).add(SubType.MOUNTAIN);
}
if (!permanent.hasSubtype(SubType.FOREST, game)) {
permanent.getSubtype(game).add(SubType.FOREST);
}
if (!permanent.hasSubtype(SubType.ISLAND, game)) {
permanent.getSubtype(game).add(SubType.ISLAND);
}
if (!permanent.hasSubtype(SubType.PLAINS, game)) {
permanent.getSubtype(game).add(SubType.PLAINS);
}
if (permanent.hasSubtype(SubType.SWAMP, game)
&& !permanent.getAbilities().containsRule(new BlackManaAbility())) {
permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
if (permanent.hasSubtype(SubType.MOUNTAIN, game)
&& !permanent.getAbilities().containsRule(new RedManaAbility())) {
permanent.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
if (permanent.hasSubtype(SubType.FOREST, game)
&& !permanent.getAbilities().containsRule(new GreenManaAbility())) {
permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
if (permanent.hasSubtype(SubType.ISLAND, game)
&& !permanent.getAbilities().containsRule(new BlueManaAbility())) {
permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
if (permanent.hasSubtype(SubType.PLAINS, game)
&& !permanent.getAbilities().containsRule(new WhiteManaAbility())) {
permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
break;
}
permanent.addSubType(
game,
SubType.PLAINS,
SubType.ISLAND,
SubType.SWAMP,
SubType.MOUNTAIN,
SubType.FOREST
);
permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game);
permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game);
permanent.addAbility(new RedManaAbility(), source.getSourceId(), game);
permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}

View file

@ -5,18 +5,12 @@ import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
/**
*
* @author LevelX2
*/
public class BecomesAuraSourceEffect extends ContinuousEffectImpl implements SourceEffect {
@ -58,9 +52,7 @@ public class BecomesAuraSourceEffect extends ContinuousEffectImpl implements Sou
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!permanent.hasSubtype(SubType.AURA, game)) {
permanent.getSubtype(game).add(SubType.AURA);
}
permanent.addSubType(game, SubType.AURA);
}
break;
case AbilityAddingRemovingEffects_6:

View file

@ -16,7 +16,7 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
protected List<SubType> landTypes = new ArrayList<>();
public BecomesBasicLandEnchantedEffect(SubType... landNames) {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
landTypes.addAll(Arrays.asList(landNames));
this.staticText = setText();
}
@ -26,68 +26,55 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl {
this.landTypes.addAll(effect.landTypes);
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public BecomesBasicLandEnchantedEffect copy() {
return new BecomesBasicLandEnchantedEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
Permanent enchantment = game.getPermanent(source.getSourceId());
if (enchantment != null && enchantment.getAttachedTo() != null) {
Permanent permanent = game.getPermanent(enchantment.getAttachedTo());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
// lands intrictically have the mana ability associated with their type, so added here in layer 4
permanent.getSubtype(game).removeAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(landTypes);
permanent.removeAllAbilities(source.getSourceId(), game);
for (SubType landType : landTypes) {
switch (landType) {
case SWAMP:
if (permanent.hasSubtype(SubType.SWAMP, game)) {
permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
break;
case MOUNTAIN:
if (permanent.hasSubtype(SubType.MOUNTAIN, game)) {
permanent.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
break;
case FOREST:
if (permanent.hasSubtype(SubType.FOREST, game)) {
permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
break;
case ISLAND:
if (permanent.hasSubtype(SubType.ISLAND, game)) {
permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
break;
case PLAINS:
if (permanent.hasSubtype(SubType.PLAINS, game)) {
permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
break;
}
}
break;
}
return true;
if (enchantment == null || enchantment.getAttachedTo() == null) {
return false;
}
Permanent permanent = game.getPermanent(enchantment.getAttachedTo());
if (permanent == null) {
return false;
}
// lands intrictically have the mana ability associated with their type, so added here in layer 4
permanent.getSubtype(game).removeAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(landTypes);
permanent.removeAllAbilities(source.getSourceId(), game);
for (SubType landType : landTypes) {
switch (landType) {
case PLAINS:
if (permanent.hasSubtype(SubType.PLAINS, game)) {
permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game);
}
break;
case ISLAND:
if (permanent.hasSubtype(SubType.ISLAND, game)) {
permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
break;
case SWAMP:
if (permanent.hasSubtype(SubType.SWAMP, game)) {
permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game);
}
break;
case MOUNTAIN:
if (permanent.hasSubtype(SubType.MOUNTAIN, game)) {
permanent.addAbility(new RedManaAbility(), source.getSourceId(), game);
}
break;
case FOREST:
if (permanent.hasSubtype(SubType.FOREST, game)) {
permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game);
}
break;
}
}
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
return true;
}
private String setText() {

View file

@ -123,7 +123,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl {
landTypesToAdd.clear();
for (SubType subtype : landTypes) {
if (!land.hasSubtype(subtype, game)) {
land.getSubtype(game).add(subtype);
land.addSubType(game, subtype);
landTypesToAdd.add(subtype);
}
}

View file

@ -60,14 +60,10 @@ public class BecomesBlackZombieAdditionEffect extends ContinuousEffectImpl {
if (creature != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (!creature.hasSubtype(SubType.ZOMBIE, game)) {
creature.getSubtype(game).add(SubType.ZOMBIE);
}
}
creature.addSubType(game, SubType.ZOMBIE);
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA && this.giveBlackColor) {
if (this.giveBlackColor) {
creature.getColor(game).setBlack(true);
}
break;

View file

@ -25,18 +25,18 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
private boolean loseTypes = false;
protected boolean loseName = false;
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor) {
this(token, theyAreStillType, filter, duration, loseColor, false, false);
}
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
this(token, theyAreStillType, filter, duration, loseColor, loseName, false);
}
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) {
public BecomesCreatureAllEffect(Token token, String theyAreStillType,
FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName, boolean loseTypes) {
super(duration, Outcome.BecomeCreature);
this.token = token;
this.theyAreStillType = theyAreStillType;
@ -44,7 +44,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
this.loseColor = loseColor;
this.loseName = loseName;
this.loseTypes = loseTypes;
this.dependencyTypes.add(DependencyType.BecomeCreature);
}
@ -87,83 +87,67 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
}
for (Permanent permanent : affectedPermanents) {
if (permanent != null) {
switch (layer) {
case TextChangingEffects_3:
if (sublayer == SubLayer.NA) {
if (loseName) {
permanent.setName(token.getName());
}
if (permanent == null) {
continue;
}
switch (layer) {
case TextChangingEffects_3:
if (loseName) {
permanent.setName(token.getName());
}
break;
case TypeChangingEffects_4:
for (CardType t : token.getCardType()) {
permanent.addCardType(t);
}
if (theyAreStillType != null || loseTypes) {
permanent.removeAllCreatureTypes(game);
}
for (SubType t : token.getSubtype(game)) {
permanent.addSubType(game, t);
}
permanent.setIsAllCreatureTypes(token.isAllCreatureTypes());
for (SuperType t : token.getSuperType()) {
if (!permanent.getSuperType().contains(t)) {
permanent.addSuperType(t);
}
break;
}
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (theyAreStillType != null) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(token.getSubtype(game));
} else {
if (loseTypes) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
}
break;
for (SubType t : token.getSubtype(game)) {
if (!permanent.hasSubtype(t, game)) {
permanent.getSubtype(game).add(t);
}
}
}
case ColorChangingEffects_5:
if (this.loseColor) {
permanent.getColor(game).setWhite(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setRed(false);
permanent.getColor(game).setGreen(false);
}
if (token.getColor(game).hasColor()) {
permanent.getColor(game).addColor(token.getColor(game));
}
break;
for (SuperType t : token.getSuperType()) {
if (!permanent.getSuperType().contains(t)) {
permanent.addSuperType(t);
}
}
for (CardType t : token.getCardType()) {
if (!permanent.getCardType().contains(t)) {
permanent.addCardType(t);
}
}
case AbilityAddingRemovingEffects_6:
if (!token.getAbilities().isEmpty()) {
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
break;
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (this.loseColor) {
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setGreen(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setWhite(false);
permanent.getColor(game).setRed(false);
}
if (token.getColor(game).hasColor()) {
permanent.getColor(game).addColor(token.getColor(game));
}
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int power = token.getPower().getValue();
int toughness = token.getToughness().getValue();
if (power != 0 && toughness != 0) {
permanent.getPower().setValue(power);
permanent.getToughness().setValue(toughness);
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
if (!token.getAbilities().isEmpty()) {
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
int power = token.getPower().getValue();
int toughness = token.getToughness().getValue();
if (power != 0 && toughness != 0) {
permanent.getPower().setValue(power);
permanent.getToughness().setValue(toughness);
}
}
break;
}
}
break;
}
}
return true;

View file

@ -78,19 +78,14 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
switch (loseType) {
case ALL:
case ALL_BUT_COLOR:
permanent.removeAllSubTypes(game);
break;
case ABILITIES_SUBTYPE:
if (permanent.isLand()) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
} else {
permanent.getSubtype(game).clear();
}
permanent.setIsAllCreatureTypes(false);
permanent.removeAllCreatureTypes(game);
break;
}
for (SubType t : token.getSubtype(game)) {
if (!permanent.hasSubtype(t, game)) {
permanent.getSubtype(game).add(t);
}
permanent.addSubType(game, t);
}
}
break;
@ -98,11 +93,11 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl {
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (loseType == LoseType.ALL || loseType == LoseType.COLOR) {
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setGreen(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setWhite(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setRed(false);
permanent.getColor(game).setGreen(false);
}
if (token.getColor(game).hasColor()) {
permanent.getColor(game).addColor(token.getColor(game));

View file

@ -1,42 +1,33 @@
package mage.abilities.effects.common.continuous;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.Token;
import mage.target.targetpointer.FixedTarget;
/**
* @author jeffwadsworth
*/
public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends ContinuousEffectImpl {
public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends OneShotEffect {
public enum LoseType {
NONE, ALL, ALL_BUT_COLOR, ABILITIES, ABILITIES_SUBTYPE_AND_PT
}
protected Token token;
protected String type;
protected LoseType loseType; // what attributes are lost
private final Token token;
private final Duration duration;
public BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(Token token, String text, Duration duration) {
this(token, text, duration, LoseType.NONE);
}
public BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(Token token, String text, Duration duration, LoseType loseType) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
this.token = token;
this.loseType = loseType;
super(Outcome.BecomeCreature);
staticText = text;
this.token = token;
this.duration = duration;
}
public BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(final BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect effect) {
super(effect);
this.token = effect.token.copy();
this.type = effect.type;
this.loseType = effect.loseType;
this.duration = effect.duration;
}
@Override
@ -44,122 +35,19 @@ public class BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect extends Co
return new BecomesCreatureAttachedWithActivatedAbilityOrSpellEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
Permanent attachedPermanent = game.getPermanent(source.getSourceId());
if (attachedPermanent != null) {
Permanent permanentAttachedTo = game.getPermanent(attachedPermanent.getAttachedTo());
if (permanentAttachedTo != null) {
affectedObjectList.add(new MageObjectReference(permanentAttachedTo, game));
}
}
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
boolean attachedExists = false;
Permanent enchantment = game.getPermanent(source.getSourceId());
if (enchantment != null) {
for (MageObjectReference mageObjectReference : affectedObjectList) {
Permanent permanentAttachedTo = mageObjectReference.getPermanent(game);
if (permanentAttachedTo != null) {
attachedExists = true;
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
for (SuperType superType : token.getSuperType()) {
permanentAttachedTo.addSuperType(superType);
}
// card type
switch (loseType) {
case ALL:
case ALL_BUT_COLOR:
permanentAttachedTo.getCardType().clear();
break;
}
for (CardType cardType : token.getCardType()) {
permanentAttachedTo.addCardType(cardType);
}
// sub type
switch (loseType) {
case ALL:
case ALL_BUT_COLOR:
case ABILITIES_SUBTYPE_AND_PT:
permanentAttachedTo.getSubtype(game).retainAll(SubType.getLandTypes());
break;
}
for (SubType subType : token.getSubtype(game)) {
if (!permanentAttachedTo.hasSubtype(subType, game)) {
permanentAttachedTo.getSubtype(game).add(subType);
}
}
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (loseType == LoseType.ALL) {
permanentAttachedTo.getColor(game).setBlack(false);
permanentAttachedTo.getColor(game).setGreen(false);
permanentAttachedTo.getColor(game).setBlue(false);
permanentAttachedTo.getColor(game).setWhite(false);
permanentAttachedTo.getColor(game).setRed(false);
}
if (token.getColor(game).hasColor()) {
permanentAttachedTo.getColor(game).setColor(token.getColor(game));
}
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
switch (loseType) {
case ALL:
case ALL_BUT_COLOR:
case ABILITIES:
case ABILITIES_SUBTYPE_AND_PT:
permanentAttachedTo.removeAllAbilities(source.getSourceId(), game);
break;
}
for (Ability ability : token.getAbilities()) {
permanentAttachedTo.addAbility(ability, source.getSourceId(), game);
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) {
permanentAttachedTo.getPower().setValue(token.getPower().getValue());
permanentAttachedTo.getToughness().setValue(token.getToughness().getValue());
}
break;
}
}
if (!attachedExists) {
discard();
}
return true;
}
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
Permanent permanent = source.getSourcePermanentOrLKI(game);
if (permanent == null) {
return false;
}
Permanent enchanted = game.getPermanent(permanent.getAttachedTo());
if (enchanted == null) {
return false;
}
game.addEffect(new BecomesCreatureTargetEffect(
token, false, true, duration
).setTargetPointer(new FixedTarget(enchanted, game)), source);
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7
|| layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.ColorChangingEffects_5
|| layer == Layer.TypeChangingEffects_4;
}
}

View file

@ -82,78 +82,66 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
} else {
permanent = game.getPermanent(source.getSourceId());
}
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (losePreviousTypes) {
permanent.getCardType().clear();
}
for (CardType cardType : token.getCardType()) {
if (permanent.getCardType().contains(cardType)) {
continue;
}
permanent.addCardType(cardType);
}
if (theyAreStillType != null && theyAreStillType.isEmpty() || theyAreStillType == null && permanent.isLand()) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
}
if (!token.getSubtype(game).isEmpty()) {
for (SubType subType : token.getSubtype(game)) {
if (permanent.hasSubtype(subType, game)) {
continue;
}
permanent.getSubtype(game).add(subType);
}
}
permanent.setIsAllCreatureTypes(token.isAllCreatureTypes());
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (token.getColor(game).hasColor()) {
permanent.getColor(game).setColor(token.getColor(game));
}
}
break;
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
if (loseAbilities) {
permanent.removeAllAbilities(source.getSourceId(), game);
}
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
break;
case PTChangingEffects_7:
if ((sublayer == SubLayer.CharacteristicDefining_7a && isCharacterDefining())
|| (sublayer == SubLayer.SetPT_7b && !isCharacterDefining())) {
if (power != null) {
permanent.getPower().setValue(power.calculate(game, source, this)); // check all other becomes to use calculate?
} else if (token.getPower() != null) {
permanent.getPower().setValue(token.getPower().getValue());
}
if (toughness != null) {
permanent.getToughness().setValue(toughness.calculate(game, source, this));
} else if (token.getToughness() != null) {
permanent.getToughness().setValue(token.getToughness().getValue());
}
}
break;
if (permanent == null) {
if (duration == Duration.Custom) {
this.discard();
}
return false;
}
switch (layer) {
case TypeChangingEffects_4:
if (losePreviousTypes) {
permanent.getCardType().clear();
}
for (CardType cardType : token.getCardType()) {
permanent.addCardType(cardType);
}
return true;
if (theyAreStillType != null && theyAreStillType.isEmpty()
|| theyAreStillType == null && permanent.isLand()) {
permanent.removeAllCreatureTypes(game);
}
if (!token.getSubtype(game).isEmpty()) {
for (SubType subType : token.getSubtype(game)) {
permanent.addSubType(game, subType);
}
}
permanent.setIsAllCreatureTypes(token.isAllCreatureTypes());
break;
} else if (duration == Duration.Custom) {
this.discard();
case ColorChangingEffects_5:
if (token.getColor(game).hasColor()) {
permanent.getColor(game).setColor(token.getColor(game));
}
break;
case AbilityAddingRemovingEffects_6:
if (loseAbilities) {
permanent.removeAllAbilities(source.getSourceId(), game);
}
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
break;
case PTChangingEffects_7:
if ((sublayer == SubLayer.CharacteristicDefining_7a && isCharacterDefining())
|| (sublayer == SubLayer.SetPT_7b && !isCharacterDefining())) {
if (power != null) {
permanent.getPower().setValue(power.calculate(game, source, this)); // check all other becomes to use calculate?
} else if (token.getPower() != null) {
permanent.getPower().setValue(token.getPower().getValue());
}
if (toughness != null) {
permanent.getToughness().setValue(toughness.calculate(game, source, this));
} else if (token.getToughness() != null) {
permanent.getToughness().setValue(token.getToughness().getValue());
}
}
break;
}
return false;
return true;
}
@Override
@ -171,7 +159,10 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4;
return layer == Layer.PTChangingEffects_7
|| layer == Layer.AbilityAddingRemovingEffects_6
|| layer == Layer.ColorChangingEffects_5
|| layer == Layer.TypeChangingEffects_4;
}
}

View file

@ -70,82 +70,68 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
boolean result = false;
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null) {
switch (layer) {
case TextChangingEffects_3:
if (sublayer == SubLayer.NA) {
if (loseName) {
permanent.setName(token.getName());
}
}
break;
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (loseAllAbilities) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.getCardType().clear(); // remove all CardTypes
permanent.getSubtype(game).addAll(token.getSubtype(game));
} else {
if (removeSubtypes) {
permanent.getSubtype(game).clear();
}
for (SubType t : token.getSubtype(game)) {
if (!permanent.hasSubtype(t, game)) {
permanent.getSubtype(game).add(t);
}
}
}
for (SuperType t : token.getSuperType()) {
if (!permanent.getSuperType().contains(t)) {
permanent.addSuperType(t);
}
}
for (CardType t : token.getCardType()) {
if (!permanent.getCardType().contains(t)) {
permanent.addCardType(t);
}
}
}
break;
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (loseAllAbilities) {
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setGreen(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setWhite(false);
permanent.getColor(game).setBlack(false);
}
if (token.getColor(game).hasColor()) {
permanent.getColor(game).setColor(token.getColor(game));
}
}
break;
case AbilityAddingRemovingEffects_6:
if (loseAllAbilities && !keepAbilities) {
permanent.removeAllAbilities(source.getSourceId(), game);
}
if (sublayer == SubLayer.NA) {
if (!token.getAbilities().isEmpty()) {
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) { // CDA can only define a characteristic of either the card or token it comes from.
permanent.getToughness().setValue(token.getToughness().getValue());
permanent.getPower().setValue(token.getPower().getValue());
}
}
result = true;
if (permanent == null) {
continue;
}
switch (layer) {
case TextChangingEffects_3:
if (loseName) {
permanent.setName(token.getName());
}
break;
case TypeChangingEffects_4:
for (CardType t : token.getCardType()) {
permanent.addCardType(t);
}
if (loseAllAbilities || removeSubtypes) {
permanent.removeAllCreatureTypes(game);
}
for (SubType t : token.getSubtype(game)) {
permanent.addSubType(game, t);
}
for (SuperType t : token.getSuperType()) {
if (!permanent.getSuperType().contains(t)) {
permanent.addSuperType(t);
}
}
break;
case ColorChangingEffects_5:
if (loseAllAbilities) {
permanent.getColor(game).setWhite(false);
permanent.getColor(game).setBlue(false);
permanent.getColor(game).setBlack(false);
permanent.getColor(game).setRed(false);
permanent.getColor(game).setGreen(false);
}
if (token.getColor(game).hasColor()) {
permanent.getColor(game).setColor(token.getColor(game));
}
break;
case AbilityAddingRemovingEffects_6:
if (loseAllAbilities && !keepAbilities) {
permanent.removeAllAbilities(source.getSourceId(), game);
}
if (sublayer == SubLayer.NA) {
if (!token.getAbilities().isEmpty()) {
for (Ability ability : token.getAbilities()) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
}
break;
case PTChangingEffects_7:
if (sublayer == SubLayer.SetPT_7b) { // CDA can only define a characteristic of either the card or token it comes from.
permanent.getToughness().setValue(token.getToughness().getValue());
permanent.getPower().setValue(token.getPower().getValue());
}
}
result = true;
}
if (!result && this.duration == Duration.Custom) {
this.discard();

View file

@ -1,8 +1,3 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
@ -19,15 +14,15 @@ import java.util.UUID;
*/
public class BecomesCreatureTypeTargetEffect extends ContinuousEffectImpl {
protected SubTypeList subtypes = new SubTypeList();
protected boolean loseOther; // loses other creature types
private final SubTypeList subtypes = new SubTypeList();
private final boolean loseOther; // loses other creature types
public BecomesCreatureTypeTargetEffect(Duration duration, SubType subtype) {
this(duration, createArrayList(subtype));
this(duration, new SubTypeList(subtype));
}
public BecomesCreatureTypeTargetEffect(Duration duration, SubType subtype, boolean loseOther) {
this(duration, createArrayList(subtype), loseOther);
this(duration, new SubTypeList(subtype), loseOther);
}
public BecomesCreatureTypeTargetEffect(Duration duration, SubTypeList subtypes) {
@ -35,67 +30,45 @@ public class BecomesCreatureTypeTargetEffect extends ContinuousEffectImpl {
}
public BecomesCreatureTypeTargetEffect(Duration duration, SubTypeList subtypes, boolean loseOther) {
super(duration, Outcome.Detriment);
this.subtypes = subtypes;
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
this.subtypes.addAll(subtypes);
this.staticText = setText();
this.loseOther = loseOther;
}
private static SubTypeList createArrayList(SubType subtype) {
SubTypeList subtypes = new SubTypeList();
subtypes.add(subtype);
return subtypes;
}
public BecomesCreatureTypeTargetEffect(final BecomesCreatureTypeTargetEffect effect) {
super(effect);
this.subtypes.addAll(effect.subtypes);
this.loseOther = effect.loseOther;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public BecomesCreatureTypeTargetEffect copy() {
return new BecomesCreatureTypeTargetEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
boolean flag = false;
for (UUID targetPermanent : targetPointer.getTargets(game, source)) {
Permanent permanent = game.getPermanent(targetPermanent);
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (loseOther) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(subtypes);
} else {
for (SubType subtype : subtypes) {
if (!permanent.hasSubtype(subtype, game)) {
permanent.getSubtype(game).add(subtype);
}
}
}
break;
}
} else {
if (duration == Duration.Custom) {
discard();
}
if (permanent == null) {
continue;
}
flag = true;
if (loseOther) {
permanent.removeAllCreatureTypes(game);
}
for (SubType subtype : subtypes) {
permanent.addSubType(game, subtype);
}
}
if (!flag && duration == Duration.Custom) {
discard();
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
private String setText() {
StringBuilder sb = new StringBuilder();
sb.append("Target creature becomes that type");

View file

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

View file

@ -75,7 +75,7 @@ public class BecomesFaceDownCreatureAllEffect extends ContinuousEffectImpl imple
permanent.getSuperType().clear();
permanent.getCardType().clear();
permanent.addCardType(CardType.CREATURE);
permanent.getSubtype(game).clear();
permanent.removeAllSubTypes(game);
permanent.getManaCost().clear();
break;
case ColorChangingEffects_5:

View file

@ -136,7 +136,7 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen
permanent.getSuperType().clear();
permanent.getCardType().clear();
permanent.addCardType(CardType.CREATURE);
permanent.getSubtype(game).clear();
permanent.removeAllSubTypes(game);
break;
case ColorChangingEffects_5:
permanent.getColor(game).setColor(new ObjectColor());

View file

@ -8,6 +8,7 @@ package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -18,33 +19,26 @@ import mage.util.SubTypeList;
*/
public class BecomesSubtypeAllEffect extends ContinuousEffectImpl {
protected SubTypeList subtypes = new SubTypeList();
protected boolean loseOther; // loses other subtypes
protected FilterCreaturePermanent filter;
private final SubTypeList subtypes = new SubTypeList();
private final boolean loseOther; // loses other subtypes
private final FilterCreaturePermanent filter;
public BecomesSubtypeAllEffect(Duration duration, SubType subtype) {
this(duration, createArrayList(subtype));
this(duration, new SubTypeList(subtype));
}
public BecomesSubtypeAllEffect(Duration duration, SubTypeList subtypes) {
this(duration, subtypes, new FilterCreaturePermanent("All creatures"), true);
this(duration, subtypes, StaticFilters.FILTER_PERMANENT_CREATURE, true);
}
public BecomesSubtypeAllEffect(Duration duration,
SubTypeList subtypes, FilterCreaturePermanent filter, boolean loseOther) {
super(duration, Outcome.Detriment);
this.subtypes = subtypes;
public BecomesSubtypeAllEffect(Duration duration, SubTypeList subtypes, FilterCreaturePermanent filter, boolean loseOther) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
this.subtypes.addAll(subtypes);
this.staticText = setText();
this.loseOther = loseOther;
this.filter = filter;
}
private static SubTypeList createArrayList(SubType subtype) {
SubTypeList subtypes = new SubTypeList();
subtypes.add(subtype);
return subtypes;
}
public BecomesSubtypeAllEffect(final BecomesSubtypeAllEffect effect) {
super(effect);
this.subtypes.addAll(effect.subtypes);
@ -52,47 +46,32 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl {
this.filter = effect.filter;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public BecomesSubtypeAllEffect copy() {
return new BecomesSubtypeAllEffect(this);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source,
Game game) {
public boolean apply(Game game, Ability source) {
boolean flag = false;
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (loseOther) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(subtypes);
} else {
for (SubType subtype : subtypes) {
if (!permanent.hasSubtype(subtype, game)) {
permanent.getSubtype(game).add(subtype);
}
}
}
break;
}
} else if (duration == Duration.Custom) {
discard();
if (permanent == null) {
continue;
}
flag = true;
if (loseOther) {
permanent.removeAllCreatureTypes(game);
}
for (SubType subtype : subtypes) {
permanent.addSubType(game, subtype);
}
}
if (!flag && duration == Duration.Custom) {
discard();
}
return true;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
private String setText() {
StringBuilder sb = new StringBuilder();
sb.append("Target creature becomes that type");

View file

@ -40,10 +40,8 @@ public class CreaturesBecomeOtherTypeEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
if (layer == Layer.TypeChangingEffects_4) {
for (Permanent object: game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) {
if (!object.hasSubtype(this.subType, game)) {
object.getSubtype(game).add(this.subType);
}
for (Permanent object : game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) {
object.addSubType(game, this.subType);
}
}

View file

@ -0,0 +1,44 @@
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 TheElk801
*/
public class GainAllCreatureTypesAttachedEffect extends ContinuousEffectImpl {
public GainAllCreatureTypesAttachedEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
staticText = "and is every creature type";
}
public GainAllCreatureTypesAttachedEffect(final GainAllCreatureTypesAttachedEffect effect) {
super(effect);
}
@Override
public GainAllCreatureTypesAttachedEffect copy() {
return new GainAllCreatureTypesAttachedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent equipment = game.getPermanent(source.getSourceId());
if (equipment == null) {
return false;
}
Permanent permanent = game.getPermanent(equipment.getAttachedTo());
if (permanent == null) {
return false;
}
permanent.setIsAllCreatureTypes(true);
return true;
}
}

View file

@ -0,0 +1,53 @@
package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.Mode;
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;
import java.util.UUID;
/**
* @author TheElk801
*/
public class GainAllCreatureTypesTargetEffect extends ContinuousEffectImpl {
public GainAllCreatureTypesTargetEffect(Duration duration) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Neutral);
}
public GainAllCreatureTypesTargetEffect(final GainAllCreatureTypesTargetEffect effect) {
super(effect);
}
@Override
public GainAllCreatureTypesTargetEffect copy() {
return new GainAllCreatureTypesTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int affectedTargets = 0;
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent target = game.getPermanent(permanentId);
if (target != null) {
target.setIsAllCreatureTypes(true);
affectedTargets++;
}
}
return affectedTargets > 0;
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
return "target " + mode.getTargets().get(0).getTargetName() + " gains all creature types " + duration.toString();
}
}

View file

@ -0,0 +1,71 @@
package mage.abilities.effects.common.continuous;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
import mage.game.Game;
import mage.util.SubTypeList;
/**
* @author TheElk801
*/
public class HasSubtypesSourceEffect extends ContinuousEffectImpl {
private final SubTypeList subtypes = new SubTypeList();
public HasSubtypesSourceEffect(SubType... subTypes) {
super(Duration.EndOfGame, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
subtypes.add(subTypes);
this.staticText = setText();
}
public HasSubtypesSourceEffect(final HasSubtypesSourceEffect effect) {
super(effect);
this.subtypes.addAll(effect.subtypes);
}
@Override
public HasSubtypesSourceEffect copy() {
return new HasSubtypesSourceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject == null) {
return false;
}
for (SubType subType : subtypes) {
sourceObject.addSubType(game, subType);
}
return true;
}
private String setText() {
String s = "{this} is also ";
switch (subtypes.size()) {
case 0:
throw new UnsupportedOperationException("Can't have zero subtypes");
case 1:
s += subtypes.get(0).getIndefiniteArticle() + " " + subtypes.get(0);
break;
case 2:
s += subtypes.get(0).getIndefiniteArticle() + " " + subtypes.get(0);
s += " and ";
s += subtypes.get(1).getIndefiniteArticle() + " " + subtypes.get(1);
break;
default:
for (int i = 0; i < subtypes.size(); i++) {
if (i == 0) {
s += subtypes.get(0).getIndefiniteArticle() + " " + subtypes.get(0) + ", ";
} else if (i == subtypes.size() - 1) {
s += "and " + subtypes.get(0);
} else {
s += subtypes.get(0) + ", ";
}
}
}
return s;
}
}

View file

@ -3,7 +3,10 @@ package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.*;
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;
@ -29,8 +32,8 @@ public class LoseAllCreatureTypesTargetEffect extends ContinuousEffectImpl {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
permanent.setIsAllCreatureTypes(false);
return permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.removeAllCreatureTypes(game);
return true;
}
return false;
}

View file

@ -24,7 +24,7 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement
* @param lessThan
*/
public LoseCreatureTypeSourceEffect(DynamicValue dynamicValue, int lessThan) {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment);
this.dynamicValue = dynamicValue;
this.lessThan = lessThan;
setText();
@ -53,31 +53,22 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
public boolean apply(Game game, Ability source) {
if (dynamicValue.calculate(game, source, this) >= lessThan) {
return false;
}
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
switch (layer) {
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
permanent.getCardType().remove(CardType.CREATURE);
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
if (permanent.isAttacking() || permanent.getBlocking() > 0) {
permanent.removeFromCombat(game);
}
}
break;
}
return true;
if (permanent == null) {
return false;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return false;
permanent.getCardType().remove(CardType.CREATURE);
if (!permanent.isTribal()) {
permanent.removeAllCreatureTypes(game);
}
if (permanent.isAttacking() || permanent.getBlocking() > 0) {
permanent.removeFromCombat(game);
}
return true;
}
private void setText() {
@ -86,10 +77,4 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement
sb.append(CardUtil.numberToText(lessThan)).append(", {this} isn't a creature");
staticText = sb.toString();
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.TypeChangingEffects_4;
}
}

View file

@ -22,20 +22,6 @@ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl {
this.setText();
}
/*public SetCardSubtypeAttachedEffect(SubType setSubtype, Duration duration, AttachmentType attachmentType) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
this.setSubtypes.add(setSubtype);
this.attachmentType = attachmentType;
setText();
}
public SetCardSubtypeAttachedEffect(List<String> setSubtypes, Duration duration, AttachmentType attachmentType) {
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
this.setSubtypes.addAll(setSubtypes);
this.attachmentType = attachmentType;
setText();
}*/
public SetCardSubtypeAttachedEffect(final SetCardSubtypeAttachedEffect effect) {
super(effect);
this.setSubtypes = effect.setSubtypes;
@ -45,13 +31,15 @@ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
Permanent equipment = game.getPermanent(source.getSourceId());
if (equipment != null && equipment.getAttachedTo() != null) {
Permanent target = game.getPermanent(equipment.getAttachedTo());
if (target != null) {
target.getSubtype(game).retainAll(SubType.getLandTypes());
target.getSubtype(game).addAll(setSubtypes);
}
if (equipment == null || equipment.getAttachedTo() == null) {
return true;
}
Permanent target = game.getPermanent(equipment.getAttachedTo());
if (target == null) {
return true;
}
target.removeAllCreatureTypes(game);
target.getSubtype(game).addAll(setSubtypes);
return true;
}

View file

@ -9,9 +9,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* IMPORTANT: This only adds the chosen subtype while the source permanent is entering the battlefield.
* You should also use @link{mage.abilities.effects.common.continuous.AddChosenSubtypeEffect} to make the subtype persist.
*
* @author LevelX2
*/
public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect {
@ -35,9 +35,7 @@ public class EnterAttributeAddChosenSubtypeEffect extends OneShotEffect {
Permanent permanent = game.getPermanentEntering(source.getSourceId());
SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type");
if (permanent != null && subtype != null) {
if (!permanent.getSubtype(game).contains(subtype)) {
permanent.getSubtype(game).add(subtype);
}
permanent.addSubType(game, subtype);
return true;
}
return false;

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword;
import mage.ObjectColor;
@ -19,7 +18,6 @@ import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author LevelX2
*/
public class EmbalmAbility extends ActivatedAbilityImpl {
@ -89,9 +87,7 @@ class EmbalmEffect extends OneShotEffect {
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.hasSubtype(SubType.ZOMBIE, game)) {
token.getSubtype(game).add(0, SubType.ZOMBIE);
}
token.addSubType(game, SubType.ZOMBIE);
token.getManaCost().clear();
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EMBALMED_CREATURE, token.getId(), source.getSourceId(), controller.getId()));
token.putOntoBattlefield(1, game, source.getSourceId(), controller.getId(), false, false, null);

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword;
import mage.ObjectColor;
@ -19,7 +18,6 @@ import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author igoudt
*/
public class EternalizeAbility extends ActivatedAbilityImpl {
@ -94,9 +92,7 @@ class EternalizeEffect extends OneShotEffect {
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.BLACK);
if (!token.hasSubtype(SubType.ZOMBIE, game)) {
token.getSubtype(game).add(0, SubType.ZOMBIE);
}
token.addSubType(game, SubType.ZOMBIE);
token.getManaCost().clear();
token.removePTCDA();
token.getPower().modifyBaseValue(4);

View file

@ -52,9 +52,10 @@ public class TransformAbility extends SimpleStaticAbility {
for (CardType type : sourceCard.getCardType()) {
permanent.addCardType(type);
}
permanent.getSubtype(game).clear();
permanent.removeAllSubTypes(game);
permanent.setIsAllCreatureTypes(sourceCard.isAllCreatureTypes());
for (SubType type : sourceCard.getSubtype(game)) {
permanent.getSubtype(game).add(type);
permanent.addSubType(game, type);
}
permanent.getSuperType().clear();
for (SuperType type : sourceCard.getSuperType()) {

View file

@ -3,11 +3,8 @@ package mage.constants;
import mage.MageObject;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.util.SubTypeList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
public enum SubType {
@ -468,6 +465,22 @@ public enum SubType {
}
}
private static final Set<SubType> landTypes = new HashSet<>();
private static final Map<SubTypeSet, Set<SubType>> subTypeSetMap = new HashMap<>();
static {
for (SubTypeSet subTypeSet : SubTypeSet.values()) {
subTypeSetMap.put(
subTypeSet,
Arrays.stream(values())
.filter(subType -> subType.getSubTypeSet() == subTypeSet)
.collect(Collectors.toSet())
);
}
landTypes.addAll(subTypeSetMap.get(SubTypeSet.BasicLandType));
landTypes.addAll(subTypeSetMap.get(SubTypeSet.NonBasicLandType));
}
private final SubTypeSet subTypeSet;
private final String description;
private final boolean customSet;
@ -534,49 +547,46 @@ public enum SubType {
return subTypeSet;
}
public static Set<SubType> getArtifactTypes() {
Set<SubType> subTypes = EnumSet.noneOf(SubType.class);
for (SubType subType : values()) {
if (subType.getSubTypeSet() == SubTypeSet.ArtifactType) {
subTypes.add(subType);
}
public boolean canGain(MageObject mageObject) {
switch (subTypeSet) {
case CreatureType:
return mageObject.isCreature() || mageObject.isTribal();
case BasicLandType:
case NonBasicLandType:
return mageObject.isLand();
case EnchantmentType:
return mageObject.isEnchantment();
case ArtifactType:
return mageObject.isArtifact();
case PlaneswalkerType:
return mageObject.isPlaneswalker();
}
return subTypes;
return false;
}
public static Set<SubType> getArtifactTypes() {
return subTypeSetMap.get(SubTypeSet.ArtifactType);
}
public static Set<SubType> getEnchantmentTypes() {
return subTypeSetMap.get(SubTypeSet.EnchantmentType);
}
public static Set<SubType> getPlaneswalkerTypes() {
Set<SubType> subTypes = EnumSet.noneOf(SubType.class);
for (SubType subType : values()) {
if (subType.getSubTypeSet() == SubTypeSet.PlaneswalkerType) {
subTypes.add(subType);
}
}
return subTypes;
return subTypeSetMap.get(SubTypeSet.PlaneswalkerType);
}
public static Set<SubType> getCreatureTypes() {
Set<SubType> subTypes = EnumSet.noneOf(SubType.class);
for (SubType subType : values()) {
if (subType.getSubTypeSet() == SubTypeSet.CreatureType) {
subTypes.add(subType);
}
}
return subTypes;
return subTypeSetMap.get(SubTypeSet.CreatureType);
}
public static Set<SubType> getBasicLands() {
return Arrays.stream(values())
.filter(p -> p.getSubTypeSet() == SubTypeSet.BasicLandType)
.collect(Collectors.toSet());
return subTypeSetMap.get(SubTypeSet.BasicLandType);
}
public static SubTypeList getLandTypes() {
SubTypeList landTypes = new SubTypeList();
for (SubType subType : values()) {
if (subType.getSubTypeSet() == SubTypeSet.BasicLandType || subType.getSubTypeSet() == SubTypeSet.NonBasicLandType) {
landTypes.add(subType);
}
}
public static Set<SubType> getLandTypes() {
return landTypes;
}
}

View file

@ -1,13 +1,11 @@
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
import mage.abilities.keyword.ChangelingAbility;
import mage.constants.CardType;
import mage.constants.SubType;
/**
*
* @author spjspj
*/
public final class CribSwapShapeshifterWhiteToken extends TokenImpl {
@ -19,6 +17,7 @@ public final class CribSwapShapeshifterWhiteToken extends TokenImpl {
subtype.add(SubType.SHAPESHIFTER);
power = new MageInt(1);
toughness = new MageInt(1);
setIsAllCreatureTypes(true);
addAbility(ChangelingAbility.getInstance());
}

View file

@ -27,6 +27,7 @@ public final class ShapeshifterToken extends TokenImpl {
subtype.add(SubType.SHAPESHIFTER);
power = new MageInt(2);
toughness = new MageInt(2);
setIsAllCreatureTypes(true);
addAbility(ChangelingAbility.getInstance());
}

View file

@ -247,7 +247,7 @@ public class Spell extends StackObjImpl implements Card {
// Otherwise effects like evolve trigger from creature comes into play event
card.getCardType().remove(CardType.CREATURE);
if (!card.getSubtype(game).contains(SubType.AURA)) {
card.getSubtype(game).add(SubType.AURA);
card.addSubType(game, SubType.AURA);
}
}
UUID permId = null;
@ -271,9 +271,7 @@ public class Spell extends StackObjImpl implements Card {
Permanent permanent = game.getPermanent(permId);
if (permanent instanceof PermanentCard) {
permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set
if (!card.getCardType().contains(CardType.CREATURE)) {
card.addCardType(CardType.CREATURE);
}
card.addCardType(CardType.CREATURE);
card.getSubtype(game).remove(SubType.AURA);
}
}

View file

@ -37,7 +37,7 @@ public class TargetCreaturePermanentWithDifferentTypes extends TargetCreaturePer
Permanent selectedCreature = game.getPermanent(targetId);
if (selectedCreature != null
&& !creature.getId().equals(selectedCreature.getId())) {
if (creature.shareSubtypes(selectedCreature, game)) {
if (creature.shareCreatureTypes(selectedCreature, game)) {
return false;
}
}

View file

@ -28,7 +28,7 @@ public class AddSubtypeApplier extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
if (!permanent.hasSubtype(subtype, game)) {
permanent.getSubtype(game).add(subtype);
permanent.addSubType(game, subtype);
}
return true;
}
@ -36,7 +36,7 @@ public class AddSubtypeApplier extends ApplyToPermanent {
@Override
public boolean apply(Game game, MageObject mageObject, Ability source, UUID copyToObjectId) {
if (!mageObject.hasSubtype(subtype, game)) {
mageObject.getSubtype(game).add(subtype);
mageObject.addSubType(game, subtype);
}
return true;
}

View file

@ -1,7 +1,5 @@
package mage.watchers.common;
import mage.abilities.keyword.ChangelingAbility;
import mage.constants.SubType;
import mage.constants.WatcherScope;
import mage.game.Game;
@ -30,22 +28,24 @@ public class ProwlWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == EventType.DAMAGED_PLAYER) {
DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event;
if (dEvent.isCombatDamage()) {
Permanent creature = game.getPermanent(dEvent.getSourceId());
if (creature != null && !allSubtypes.contains(creature.getControllerId())) {
if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.isAllCreatureTypes()) {
allSubtypes.add(creature.getControllerId());
} else {
Set<SubType> subtypes = damagingSubtypes.getOrDefault(creature.getControllerId(), new LinkedHashSet<>());
subtypes.addAll(creature.getSubtype(game));
damagingSubtypes.put(creature.getControllerId(), subtypes);
}
}
}
if (event.getType() != EventType.DAMAGED_PLAYER) {
return;
}
DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event;
if (!dEvent.isCombatDamage()) {
return;
}
Permanent creature = game.getPermanent(dEvent.getSourceId());
if (creature == null || allSubtypes.contains(creature.getControllerId())) {
return;
}
if (creature.isAllCreatureTypes()) {
allSubtypes.add(creature.getControllerId());
return;
}
damagingSubtypes
.computeIfAbsent(creature.getControllerId(), m -> new LinkedHashSet<>())
.addAll(creature.getSubtype(game));
}
@Override