mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 13:19:18 -08:00
Merge branch 'master' into feature/implement-harmonize-ability
This commit is contained in:
commit
2fbd7624b9
150 changed files with 5325 additions and 843 deletions
|
|
@ -6,8 +6,8 @@ import mage.MageObject;
|
|||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.VariableManaCost;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.AdventureCardSpell;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SpellOptionCard;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
|
|
@ -99,7 +99,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
// forced to cast (can be part id or main id)
|
||||
Set<UUID> idsToCheck = new HashSet<>();
|
||||
idsToCheck.add(object.getId());
|
||||
if (object instanceof Card && !(object instanceof AdventureCardSpell)) {
|
||||
if (object instanceof Card && !(object instanceof SpellOptionCard)) {
|
||||
idsToCheck.add(((Card) object).getMainCard().getId());
|
||||
}
|
||||
for (UUID idToCheck : idsToCheck) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class BecomesTargetAnyTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) {
|
||||
return false;
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
|
||||
if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class BecomesTargetAttachedTriggeredAbility extends TriggeredAbilityImpl
|
|||
if (enchantment == null || enchantment.getAttachedTo() == null || !event.getTargetId().equals(enchantment.getAttachedTo())) {
|
||||
return false;
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
|
||||
if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class BecomesTargetControllerTriggeredAbility extends TriggeredAbilityImp
|
|||
return false;
|
||||
}
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
|
||||
if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public class BecomesTargetSourceTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (!event.getTargetId().equals(getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
|
||||
if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package mage.abilities.condition.common;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.cards.AdventureCardSpell;
|
||||
import mage.cards.SpellOptionCard;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.ModalDoubleFacedCardHalf;
|
||||
import mage.cards.SplitCardHalf;
|
||||
|
|
@ -20,7 +20,7 @@ public enum IsBeingCastFromHandCondition implements Condition {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObject object = game.getObject(source);
|
||||
if (object instanceof SplitCardHalf || object instanceof AdventureCardSpell || object instanceof ModalDoubleFacedCardHalf) {
|
||||
if (object instanceof SplitCardHalf || object instanceof SpellOptionCard || object instanceof ModalDoubleFacedCardHalf) {
|
||||
UUID mainCardId = ((Card) object).getMainCard().getId();
|
||||
object = game.getObject(mainCardId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
/**
|
||||
* @author androosss
|
||||
*/
|
||||
public enum YouCastExactOneSpellThisTurnCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
return watcher != null && watcher.getSpellsCastThisTurn(source.getControllerId()).size() == 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -549,9 +549,9 @@ public class ContinuousEffects implements Serializable {
|
|||
// rules:
|
||||
// 708.4. In every zone except the stack, the characteristics of a split card are those of its two halves combined.
|
||||
idToCheck = ((SplitCardHalf) objectToCheck).getMainCard().getId();
|
||||
} else if (!type.needPlayCardAbility() && objectToCheck instanceof AdventureCardSpell) {
|
||||
// adventure spell uses alternative characteristics for spell/stack, all other cases must use main card
|
||||
idToCheck = ((AdventureCardSpell) objectToCheck).getMainCard().getId();
|
||||
} else if (!type.needPlayCardAbility() && objectToCheck instanceof CardWithSpellOption) {
|
||||
// adventure/omen spell uses alternative characteristics for spell/stack, all other cases must use main card
|
||||
idToCheck = ((CardWithSpellOption) objectToCheck).getMainCard().getId();
|
||||
} else if (!type.needPlayCardAbility() && objectToCheck instanceof ModalDoubleFacedCardHalf) {
|
||||
// each mdf side uses own characteristics to check for playing, all other cases must use main card
|
||||
// rules:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import mage.abilities.MageSingleton;
|
|||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.AdventureCardSpell;
|
||||
import mage.cards.AdventureSpellCard;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -51,10 +51,10 @@ public class ExileAdventureSpellEffect extends OneShotEffect implements MageSing
|
|||
Spell spell = game.getStack().getSpell(source.getId());
|
||||
if (spell != null) {
|
||||
Card spellCard = spell.getCard();
|
||||
if (spellCard instanceof AdventureCardSpell) {
|
||||
if (spellCard instanceof AdventureSpellCard) {
|
||||
UUID exileId = adventureExileId(controller.getId(), game);
|
||||
game.getExile().createZone(exileId, "On an Adventure from " + controller.getName());
|
||||
AdventureCardSpell adventureSpellCard = (AdventureCardSpell) spellCard;
|
||||
AdventureSpellCard adventureSpellCard = (AdventureSpellCard) spellCard;
|
||||
Card parentCard = adventureSpellCard.getParentCard();
|
||||
if (controller.moveCardsToExile(parentCard, source, game, true, exileId, "On an Adventure from " + controller.getName())) {
|
||||
ContinuousEffect effect = new AdventureCastFromExileEffect();
|
||||
|
|
|
|||
|
|
@ -39,12 +39,19 @@ public class EndureSourceEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return doEndure(source.getSourcePermanentOrLKI(game), 1, game, source);
|
||||
}
|
||||
|
||||
public static boolean doEndure(Permanent permanent, int amount, Game game, Ability source) {
|
||||
if (permanent == null || amount < 1) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent != null && player.chooseUse(
|
||||
Player controller = game.getPlayer(permanent.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
if (permanent.getZoneChangeCounter(game) == game.getState().getZoneChangeCounter(permanent.getId())
|
||||
&& controller.chooseUse(
|
||||
Outcome.BoostCreature, "Put " + CardUtil.numberToText(amount, "a") + " +1/+1 counter" +
|
||||
(amount > 1 ? "s" : "") + " on " + permanent.getName() + " or create " +
|
||||
CardUtil.addArticle("" + amount) + ' ' + amount + '/' + amount + " Spirit token?",
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ public class ForetellAbility extends SpecialAction {
|
|||
game.getState().addOtherAbility(rightHalfCard, ability);
|
||||
}
|
||||
}
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
if (foretellCost != null) {
|
||||
Card creatureCard = card.getMainCard();
|
||||
ForetellCostAbility ability = new ForetellCostAbility(foretellCost);
|
||||
|
|
@ -268,7 +268,7 @@ public class ForetellAbility extends SpecialAction {
|
|||
game.getState().addOtherAbility(creatureCard, ability);
|
||||
}
|
||||
if (foretellSplitCost != null) {
|
||||
Card spellCard = ((AdventureCard) card).getSpellCard();
|
||||
Card spellCard = ((CardWithSpellOption) card).getSpellCard();
|
||||
ForetellCostAbility ability = new ForetellCostAbility(foretellSplitCost);
|
||||
ability.setSourceId(spellCard.getId());
|
||||
ability.setControllerId(source.getControllerId());
|
||||
|
|
@ -360,11 +360,11 @@ public class ForetellAbility extends SpecialAction {
|
|||
} else if (((ModalDoubleFacedCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||
return ((ModalDoubleFacedCard) card).getRightHalfCard().getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
if (card.getMainCard().getName().equals(abilityName)) {
|
||||
return card.getMainCard().getSpellAbility().canActivate(playerId, game);
|
||||
} else if (((AdventureCard) card).getSpellCard().getName().equals(abilityName)) {
|
||||
return ((AdventureCard) card).getSpellCard().getSpellAbility().canActivate(playerId, game);
|
||||
} else if (((CardWithSpellOption) card).getSpellCard().getName().equals(abilityName)) {
|
||||
return ((CardWithSpellOption) card).getSpellCard().getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
}
|
||||
return card.getSpellAbility().canActivate(playerId, game);
|
||||
|
|
@ -391,11 +391,11 @@ public class ForetellAbility extends SpecialAction {
|
|||
} else if (((ModalDoubleFacedCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((ModalDoubleFacedCard) card).getRightHalfCard().getSpellAbility().copy();
|
||||
}
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
if (card.getMainCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = card.getMainCard().getSpellAbility().copy();
|
||||
} else if (((AdventureCard) card).getSpellCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((AdventureCard) card).getSpellCard().getSpellAbility().copy();
|
||||
} else if (((CardWithSpellOption) card).getSpellCard().getName().equals(abilityName)) {
|
||||
spellAbilityCopy = ((CardWithSpellOption) card).getSpellCard().getSpellAbility().copy();
|
||||
}
|
||||
} else {
|
||||
spellAbilityCopy = card.getSpellAbility().copy();
|
||||
|
|
|
|||
|
|
@ -268,11 +268,11 @@ class PlotSpellAbility extends SpellAbility {
|
|||
} else if (((CardWithHalves) mainCard).getRightHalfCard().getName().equals(faceCardName)) {
|
||||
return ((CardWithHalves) mainCard).getRightHalfCard().getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
if (card.getMainCard().getName().equals(faceCardName)) {
|
||||
return card.getMainCard().getSpellAbility().canActivate(playerId, game);
|
||||
} else if (((AdventureCard) card).getSpellCard().getName().equals(faceCardName)) {
|
||||
return ((AdventureCard) card).getSpellCard().getSpellAbility().canActivate(playerId, game);
|
||||
} else if (((CardWithSpellOption) card).getSpellCard().getName().equals(faceCardName)) {
|
||||
return ((CardWithSpellOption) card).getSpellCard().getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
}
|
||||
return card.getSpellAbility().canActivate(playerId, game);
|
||||
|
|
@ -294,11 +294,11 @@ class PlotSpellAbility extends SpellAbility {
|
|||
} else if (((CardWithHalves) card).getRightHalfCard().getName().equals(faceCardName)) {
|
||||
spellAbilityCopy = ((CardWithHalves) card).getRightHalfCard().getSpellAbility().copy();
|
||||
}
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
if (card.getMainCard().getName().equals(faceCardName)) {
|
||||
spellAbilityCopy = card.getMainCard().getSpellAbility().copy();
|
||||
} else if (((AdventureCard) card).getSpellCard().getName().equals(faceCardName)) {
|
||||
spellAbilityCopy = ((AdventureCard) card).getSpellCard().getSpellAbility().copy();
|
||||
} else if (((CardWithSpellOption) card).getSpellCard().getName().equals(faceCardName)) {
|
||||
spellAbilityCopy = ((CardWithSpellOption) card).getSpellCard().getSpellAbility().copy();
|
||||
}
|
||||
} else {
|
||||
spellAbilityCopy = card.getSpellAbility().copy();
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public class WardAbility extends TriggeredAbilityImpl {
|
|||
if (!getSourceId().equals(event.getTargetId())) {
|
||||
return false;
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getId().toString(), event, game);
|
||||
if (targetingObject == null || !game.getOpponents(getControllerId()).contains(targetingObject.getControllerId())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,98 +1,29 @@
|
|||
package mage.cards;
|
||||
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author phulin
|
||||
*/
|
||||
public abstract class AdventureCard extends CardImpl {
|
||||
|
||||
/* The adventure spell card, i.e. Swift End. */
|
||||
protected AdventureCardSpell spellCard;
|
||||
public abstract class AdventureCard extends CardWithSpellOption {
|
||||
|
||||
public AdventureCard(UUID ownerId, CardSetInfo setInfo, CardType[] types, CardType[] typesSpell, String costs, String adventureName, String costsSpell) {
|
||||
super(ownerId, setInfo, types, costs);
|
||||
this.spellCard = new AdventureCardSpellImpl(ownerId, setInfo, adventureName, typesSpell, costsSpell, this);
|
||||
this.spellCard = new AdventureSpellCard(ownerId, setInfo, adventureName, typesSpell, costsSpell, this);
|
||||
}
|
||||
|
||||
public AdventureCard(AdventureCard card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
public void finalizeAdventure() {
|
||||
spellCard.finalizeAdventure();
|
||||
}
|
||||
|
||||
protected AdventureCard(final AdventureCard card) {
|
||||
super(card);
|
||||
this.spellCard = card.getSpellCard().copy();
|
||||
this.spellCard.setParentCard(this);
|
||||
}
|
||||
|
||||
public AdventureCardSpell getSpellCard() {
|
||||
return spellCard;
|
||||
}
|
||||
|
||||
public void setParts(AdventureCardSpell cardSpell) {
|
||||
// for card copy only - set new parts
|
||||
this.spellCard = cardSpell;
|
||||
cardSpell.setParentCard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignNewId() {
|
||||
super.assignNewId();
|
||||
spellCard.assignNewId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
||||
Zone currentZone = game.getState().getZone(getId());
|
||||
game.getState().setZone(getSpellCard().getId(), currentZone);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZone(Zone zone, Game game) {
|
||||
super.setZone(zone, game);
|
||||
game.setZone(getSpellCard().getId(), zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
if (super.moveToExile(exileId, name, source, game, appliedEffects)) {
|
||||
Zone currentZone = game.getState().getZone(getId());
|
||||
game.getState().setZone(getSpellCard().getId(), currentZone);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromZone(Game game, Zone fromZone, Ability source) {
|
||||
// zone contains only one main card
|
||||
return super.removeFromZone(game, fromZone, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) {
|
||||
if (isCopy()) { // same as meld cards
|
||||
super.updateZoneChangeCounter(game, event);
|
||||
return;
|
||||
}
|
||||
super.updateZoneChangeCounter(game, event);
|
||||
getSpellCard().updateZoneChangeCounter(game, event);
|
||||
spellCard.finalizeSpell();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -103,45 +34,4 @@ public abstract class AdventureCard extends CardImpl {
|
|||
this.getSpellCard().getSpellAbility().setControllerId(controllerId);
|
||||
return super.cast(game, fromZone, ability, controllerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
Abilities<Ability> allAbilities = new AbilitiesImpl<>();
|
||||
allAbilities.addAll(spellCard.getAbilities());
|
||||
allAbilities.addAll(super.getAbilities());
|
||||
return allAbilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getInitAbilities() {
|
||||
// must init only parent related abilities, spell card must be init separately
|
||||
return super.getAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
Abilities<Ability> allAbilities = new AbilitiesImpl<>();
|
||||
allAbilities.addAll(spellCard.getAbilities(game));
|
||||
allAbilities.addAll(super.getAbilities(game));
|
||||
return allAbilities;
|
||||
}
|
||||
|
||||
public Abilities<Ability> getSharedAbilities(Game game) {
|
||||
// abilities without spellcard
|
||||
return super.getAbilities(game);
|
||||
}
|
||||
|
||||
public List<String> getSharedRules(Game game) {
|
||||
// rules without spellcard
|
||||
Abilities<Ability> sourceAbilities = this.getSharedAbilities(game);
|
||||
return CardUtil.getCardRulesWithAdditionalInfo(game, this, sourceAbilities, sourceAbilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnerId(UUID ownerId) {
|
||||
super.setOwnerId(ownerId);
|
||||
abilities.setControllerId(ownerId);
|
||||
spellCard.getAbilities().setControllerId(ownerId);
|
||||
spellCard.setOwnerId(ownerId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
package mage.cards;
|
||||
|
||||
/**
|
||||
* @author phulin
|
||||
*/
|
||||
public interface AdventureCardSpell extends SubCard<AdventureCard> {
|
||||
|
||||
@Override
|
||||
AdventureCardSpell copy();
|
||||
|
||||
void finalizeAdventure();
|
||||
}
|
||||
|
|
@ -19,11 +19,11 @@ import java.util.stream.Collectors;
|
|||
/**
|
||||
* @author phulin
|
||||
*/
|
||||
public class AdventureCardSpellImpl extends CardImpl implements AdventureCardSpell {
|
||||
public class AdventureSpellCard extends CardImpl implements SpellOptionCard {
|
||||
|
||||
private AdventureCard adventureCardParent;
|
||||
|
||||
public AdventureCardSpellImpl(UUID ownerId, CardSetInfo setInfo, String adventureName, CardType[] cardTypes, String costs, AdventureCard adventureCardParent) {
|
||||
public AdventureSpellCard(UUID ownerId, CardSetInfo setInfo, String adventureName, CardType[] cardTypes, String costs, AdventureCard adventureCardParent) {
|
||||
super(ownerId, setInfo, cardTypes, costs, SpellAbilityType.ADVENTURE_SPELL);
|
||||
this.subtype.add(SubType.ADVENTURE);
|
||||
|
||||
|
|
@ -35,13 +35,13 @@ public class AdventureCardSpellImpl extends CardImpl implements AdventureCardSpe
|
|||
this.adventureCardParent = adventureCardParent;
|
||||
}
|
||||
|
||||
public void finalizeAdventure() {
|
||||
public void finalizeSpell() {
|
||||
if (spellAbility instanceof AdventureCardSpellAbility) {
|
||||
((AdventureCardSpellAbility) spellAbility).finalizeAdventure();
|
||||
}
|
||||
}
|
||||
|
||||
protected AdventureCardSpellImpl(final AdventureCardSpellImpl card) {
|
||||
protected AdventureSpellCard(final AdventureSpellCard card) {
|
||||
super(card);
|
||||
this.adventureCardParent = card.adventureCardParent;
|
||||
}
|
||||
|
|
@ -83,13 +83,13 @@ public class AdventureCardSpellImpl extends CardImpl implements AdventureCardSpe
|
|||
}
|
||||
|
||||
@Override
|
||||
public AdventureCardSpellImpl copy() {
|
||||
return new AdventureCardSpellImpl(this);
|
||||
public AdventureSpellCard copy() {
|
||||
return new AdventureSpellCard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentCard(AdventureCard card) {
|
||||
this.adventureCardParent = card;
|
||||
public void setParentCard(CardWithSpellOption card) {
|
||||
this.adventureCardParent = (AdventureCard) card;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -102,6 +102,11 @@ public class AdventureCardSpellImpl extends CardImpl implements AdventureCardSpe
|
|||
// id must send to main card (popup card hint in game logs)
|
||||
return getName() + " [" + adventureCardParent.getId().toString().substring(0, 3) + ']';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpellType() {
|
||||
return "Adventure";
|
||||
}
|
||||
}
|
||||
|
||||
class AdventureCardSpellAbility extends SpellAbility {
|
||||
|
|
@ -141,8 +146,8 @@ class AdventureCardSpellAbility extends SpellAbility {
|
|||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||
ExileZone adventureExileZone = game.getExile().getExileZone(ExileAdventureSpellEffect.adventureExileId(playerId, game));
|
||||
Card spellCard = game.getCard(this.getSourceId());
|
||||
if (spellCard instanceof AdventureCardSpell) {
|
||||
Card card = ((AdventureCardSpell) spellCard).getParentCard();
|
||||
if (spellCard instanceof AdventureSpellCard) {
|
||||
Card card = ((AdventureSpellCard) spellCard).getParentCard();
|
||||
if (adventureExileZone != null && adventureExileZone.contains(card.getId())) {
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
|
|
@ -530,8 +530,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
}
|
||||
|
||||
if (stackObject == null && (this instanceof AdventureCard)) {
|
||||
stackObject = game.getStack().getSpell(((AdventureCard) this).getSpellCard().getId(), false);
|
||||
if (stackObject == null && (this instanceof CardWithSpellOption)) {
|
||||
stackObject = game.getStack().getSpell(((CardWithSpellOption) this).getSpellCard().getId(), false);
|
||||
}
|
||||
|
||||
if (stackObject == null) {
|
||||
|
|
|
|||
131
Mage/src/main/java/mage/cards/CardWithSpellOption.java
Normal file
131
Mage/src/main/java/mage/cards/CardWithSpellOption.java
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
package mage.cards;
|
||||
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author phulin, jmlundeen
|
||||
*/
|
||||
public abstract class CardWithSpellOption extends CardImpl {
|
||||
|
||||
/* The adventure/omen spell card, i.e. Swift End. */
|
||||
protected SpellOptionCard spellCard;
|
||||
|
||||
public CardWithSpellOption(UUID ownerId, CardSetInfo setInfo, CardType[] types, String costs) {
|
||||
super(ownerId, setInfo, types, costs);
|
||||
}
|
||||
|
||||
public CardWithSpellOption(CardWithSpellOption card) {
|
||||
super(card);
|
||||
this.spellCard = card.getSpellCard().copy();
|
||||
this.spellCard.setParentCard(this);
|
||||
}
|
||||
|
||||
public SpellOptionCard getSpellCard() {
|
||||
return spellCard;
|
||||
}
|
||||
|
||||
public void setParts(SpellOptionCard cardSpell) {
|
||||
// for card copy only - set new parts
|
||||
this.spellCard = cardSpell;
|
||||
cardSpell.setParentCard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignNewId() {
|
||||
super.assignNewId();
|
||||
spellCard.assignNewId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
if (super.moveToZone(toZone, source, game, flag, appliedEffects)) {
|
||||
Zone currentZone = game.getState().getZone(getId());
|
||||
game.getState().setZone(getSpellCard().getId(), currentZone);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZone(Zone zone, Game game) {
|
||||
super.setZone(zone, game);
|
||||
game.setZone(getSpellCard().getId(), zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
if (super.moveToExile(exileId, name, source, game, appliedEffects)) {
|
||||
Zone currentZone = game.getState().getZone(getId());
|
||||
game.getState().setZone(getSpellCard().getId(), currentZone);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromZone(Game game, Zone fromZone, Ability source) {
|
||||
// zone contains only one main card
|
||||
return super.removeFromZone(game, fromZone, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) {
|
||||
if (isCopy()) { // same as meld cards
|
||||
super.updateZoneChangeCounter(game, event);
|
||||
return;
|
||||
}
|
||||
super.updateZoneChangeCounter(game, event);
|
||||
getSpellCard().updateZoneChangeCounter(game, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
Abilities<Ability> allAbilities = new AbilitiesImpl<>();
|
||||
allAbilities.addAll(spellCard.getAbilities());
|
||||
allAbilities.addAll(super.getAbilities());
|
||||
return allAbilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getInitAbilities() {
|
||||
// must init only parent related abilities, spell card must be init separately
|
||||
return super.getAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
Abilities<Ability> allAbilities = new AbilitiesImpl<>();
|
||||
allAbilities.addAll(spellCard.getAbilities(game));
|
||||
allAbilities.addAll(super.getAbilities(game));
|
||||
return allAbilities;
|
||||
}
|
||||
|
||||
public Abilities<Ability> getSharedAbilities(Game game) {
|
||||
// abilities without spellCard
|
||||
return super.getAbilities(game);
|
||||
}
|
||||
|
||||
public List<String> getSharedRules(Game game) {
|
||||
// rules without spellCard
|
||||
Abilities<Ability> sourceAbilities = this.getSharedAbilities(game);
|
||||
return CardUtil.getCardRulesWithAdditionalInfo(game, this, sourceAbilities, sourceAbilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnerId(UUID ownerId) {
|
||||
super.setOwnerId(ownerId);
|
||||
abilities.setControllerId(ownerId);
|
||||
spellCard.getAbilities().setControllerId(ownerId);
|
||||
spellCard.setOwnerId(ownerId);
|
||||
}
|
||||
}
|
||||
34
Mage/src/main/java/mage/cards/OmenCard.java
Normal file
34
Mage/src/main/java/mage/cards/OmenCard.java
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package mage.cards;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class OmenCard extends CardWithSpellOption {
|
||||
|
||||
public OmenCard(UUID ownerId, CardSetInfo setInfo, CardType[] types, CardType[] typesSpell, String costs, String omenName, String costsSpell) {
|
||||
super(ownerId, setInfo, types, costs);
|
||||
this.spellCard = new OmenSpellCard(ownerId, setInfo, omenName, typesSpell, costsSpell, this);
|
||||
}
|
||||
|
||||
public OmenCard(OmenCard card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
public void finalizeOmen() {
|
||||
spellCard.finalizeSpell();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
|
||||
if (ability.getSpellAbilityType() == SpellAbilityType.OMEN_SPELL) {
|
||||
return this.getSpellCard().cast(game, fromZone, ability, controllerId);
|
||||
}
|
||||
this.getSpellCard().getSpellAbility().setControllerId(controllerId);
|
||||
return super.cast(game, fromZone, ability, controllerId);
|
||||
}
|
||||
}
|
||||
174
Mage/src/main/java/mage/cards/OmenSpellCard.java
Normal file
174
Mage/src/main/java/mage/cards/OmenSpellCard.java
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
package mage.cards;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class OmenSpellCard extends CardImpl implements SpellOptionCard {
|
||||
|
||||
private OmenCard omenCardParent;
|
||||
|
||||
public OmenSpellCard(UUID ownerId, CardSetInfo setInfo, String omenName, CardType[] cardTypes, String costs, OmenCard omenCard) {
|
||||
super(ownerId, setInfo, cardTypes, costs, SpellAbilityType.OMEN_SPELL);
|
||||
this.subtype.add(SubType.OMEN);
|
||||
|
||||
OmenCardSpellAbility newSpellAbility = new OmenCardSpellAbility(getSpellAbility(), omenName, cardTypes, costs);
|
||||
this.replaceSpellAbility(newSpellAbility);
|
||||
spellAbility = newSpellAbility;
|
||||
|
||||
this.setName(omenName);
|
||||
this.omenCardParent = omenCard;
|
||||
}
|
||||
|
||||
public void finalizeSpell() {
|
||||
if (spellAbility instanceof OmenCardSpellAbility) {
|
||||
((OmenCardSpellAbility) spellAbility).finalizeOmen();
|
||||
}
|
||||
}
|
||||
|
||||
protected OmenSpellCard(final OmenSpellCard card) {
|
||||
super(card);
|
||||
this.omenCardParent = card.omenCardParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getOwnerId() {
|
||||
return omenCardParent.getOwnerId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpansionSetCode() {
|
||||
return omenCardParent.getExpansionSetCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCardNumber() {
|
||||
return omenCardParent.getCardNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
return omenCardParent.moveToZone(toZone, source, game, flag, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
return omenCardParent.moveToExile(exileId, name, source, game, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmenCard getMainCard() {
|
||||
return omenCardParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZone(Zone zone, Game game) {
|
||||
game.setZone(omenCardParent.getId(), zone);
|
||||
game.setZone(omenCardParent.getSpellCard().getId(), zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmenSpellCard copy() {
|
||||
return new OmenSpellCard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentCard(CardWithSpellOption card) {
|
||||
this.omenCardParent = (OmenCard) card;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmenCard getParentCard() {
|
||||
return this.omenCardParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdName() {
|
||||
// id must send to main card (popup card hint in game logs)
|
||||
return getName() + " [" + omenCardParent.getId().toString().substring(0, 3) + ']';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpellType() {
|
||||
return "Omen";
|
||||
}
|
||||
}
|
||||
|
||||
class OmenCardSpellAbility extends SpellAbility {
|
||||
|
||||
private String nameFull;
|
||||
private boolean finalized = false;
|
||||
|
||||
public OmenCardSpellAbility(final SpellAbility baseSpellAbility, String omenName, CardType[] cardTypes, String costs) {
|
||||
super(baseSpellAbility);
|
||||
this.setName(cardTypes, omenName, costs);
|
||||
this.setCardName(omenName);
|
||||
}
|
||||
|
||||
public void finalizeOmen() {
|
||||
if (finalized) {
|
||||
throw new IllegalStateException("Wrong code usage. "
|
||||
+ "Omen (" + cardName + ") "
|
||||
+ "need to call finalizeOmen() exactly once.");
|
||||
}
|
||||
Effect effect = new ShuffleIntoLibrarySourceEffect();
|
||||
effect.setText("");
|
||||
this.addEffect(effect);
|
||||
this.finalized = true;
|
||||
}
|
||||
|
||||
protected OmenCardSpellAbility(final OmenCardSpellAbility ability) {
|
||||
super(ability);
|
||||
this.nameFull = ability.nameFull;
|
||||
if (!ability.finalized) {
|
||||
throw new IllegalStateException("Wrong code usage. "
|
||||
+ "Omen (" + cardName + ") "
|
||||
+ "need to call finalizeOmen() at the very end of the card's constructor.");
|
||||
}
|
||||
this.finalized = true;
|
||||
}
|
||||
|
||||
public void setName(CardType[] cardTypes, String omenName, String costs) {
|
||||
this.nameFull = "Omen " + Arrays.stream(cardTypes).map(CardType::toString).collect(Collectors.joining(" ")) + " — " + omenName;
|
||||
this.name = this.nameFull + " " + costs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule(boolean all) {
|
||||
return this.getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sbRule = new StringBuilder();
|
||||
sbRule.append(this.nameFull);
|
||||
sbRule.append(" ");
|
||||
sbRule.append(getManaCosts().getText());
|
||||
sbRule.append(" — ");
|
||||
Modes modes = this.getModes();
|
||||
if (modes.size() <= 1) {
|
||||
sbRule.append(modes.getMode().getEffects().getTextStartingUpperCase(modes.getMode()));
|
||||
} else {
|
||||
sbRule.append(getModes().getText());
|
||||
}
|
||||
sbRule.append(" <i>(Then shuffle this card into its owner's library.)<i>");
|
||||
return sbRule.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OmenCardSpellAbility copy() {
|
||||
return new OmenCardSpellAbility(this);
|
||||
}
|
||||
}
|
||||
18
Mage/src/main/java/mage/cards/SpellOptionCard.java
Normal file
18
Mage/src/main/java/mage/cards/SpellOptionCard.java
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package mage.cards;
|
||||
|
||||
public interface SpellOptionCard extends SubCard<CardWithSpellOption> {
|
||||
|
||||
@Override
|
||||
SpellOptionCard copy();
|
||||
|
||||
/**
|
||||
* Adds the final shared ability to the card. e.g. Adventure exile effect / Omen shuffle effect
|
||||
*/
|
||||
void finalizeSpell();
|
||||
|
||||
/**
|
||||
* Used to get the card type text such as Adventure. Currently only used in {@link mage.game.stack.Spell#getSpellCastText Spell} for logging the spell
|
||||
* being cast as part of the two part card.
|
||||
*/
|
||||
String getSpellType();
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ import java.util.List;
|
|||
*/
|
||||
public class MockCard extends CardImpl implements MockableCard {
|
||||
|
||||
public static String ADVENTURE_NAME_SEPARATOR = " // ";
|
||||
public static String CARD_WITH_SPELL_OPTION_NAME_SEPARATOR = " // ";
|
||||
public static String MODAL_DOUBLE_FACES_NAME_SEPARATOR = " // ";
|
||||
|
||||
// Needs to be here, as it is normally calculated from the
|
||||
|
|
@ -34,7 +34,7 @@ public class MockCard extends CardImpl implements MockableCard {
|
|||
protected List<String> manaCostLeftStr;
|
||||
protected List<String> manaCostRightStr;
|
||||
protected List<String> manaCostStr;
|
||||
protected String adventureSpellName;
|
||||
protected String spellOptionName; // adventure/omen spell name
|
||||
protected boolean isModalDoubleFacedCard;
|
||||
protected int manaValue;
|
||||
|
||||
|
|
@ -71,8 +71,8 @@ public class MockCard extends CardImpl implements MockableCard {
|
|||
this.secondSideCard = new MockCard(CardRepository.instance.findCardWithPreferredSetAndNumber(card.getSecondSideName(), card.getSetCode(), card.getCardNumber()));
|
||||
}
|
||||
|
||||
if (card.isAdventureCard()) {
|
||||
this.adventureSpellName = card.getAdventureSpellName();
|
||||
if (card.isCardWithSpellOption()) {
|
||||
this.spellOptionName = card.getSpellOptionCardName();
|
||||
}
|
||||
|
||||
if (card.isModalDoubleFacedCard()) {
|
||||
|
|
@ -101,7 +101,7 @@ public class MockCard extends CardImpl implements MockableCard {
|
|||
this.manaCostLeftStr = new ArrayList<>(card.manaCostLeftStr);
|
||||
this.manaCostRightStr = new ArrayList<>(card.manaCostRightStr);
|
||||
this.manaCostStr = new ArrayList<>(card.manaCostStr);
|
||||
this.adventureSpellName = card.adventureSpellName;
|
||||
this.spellOptionName = card.spellOptionName;
|
||||
this.isModalDoubleFacedCard = card.isModalDoubleFacedCard;
|
||||
this.manaValue = card.manaValue;
|
||||
}
|
||||
|
|
@ -155,8 +155,8 @@ public class MockCard extends CardImpl implements MockableCard {
|
|||
return getName();
|
||||
}
|
||||
|
||||
if (adventureSpellName != null) {
|
||||
return getName() + ADVENTURE_NAME_SEPARATOR + adventureSpellName;
|
||||
if (spellOptionName != null) {
|
||||
return getName() + CARD_WITH_SPELL_OPTION_NAME_SEPARATOR + spellOptionName;
|
||||
} else if (isModalDoubleFacedCard) {
|
||||
return getName() + MODAL_DOUBLE_FACES_NAME_SEPARATOR + this.getSecondCardFace().getName();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ public class CardInfo {
|
|||
@DatabaseField
|
||||
protected String secondSideName;
|
||||
@DatabaseField
|
||||
protected boolean adventureCard;
|
||||
protected boolean cardWithSpellOption;
|
||||
@DatabaseField
|
||||
protected String adventureSpellName;
|
||||
protected String spellOptionCardName;
|
||||
@DatabaseField
|
||||
protected boolean modalDoubleFacedCard;
|
||||
@DatabaseField
|
||||
|
|
@ -157,9 +157,9 @@ public class CardInfo {
|
|||
this.secondSideName = secondSide.getName();
|
||||
}
|
||||
|
||||
if (card instanceof AdventureCard) {
|
||||
this.adventureCard = true;
|
||||
this.adventureSpellName = ((AdventureCard) card).getSpellCard().getName();
|
||||
if (card instanceof CardWithSpellOption) {
|
||||
this.cardWithSpellOption = true;
|
||||
this.spellOptionCardName = ((CardWithSpellOption) card).getSpellCard().getName();
|
||||
}
|
||||
|
||||
if (card instanceof ModalDoubleFacedCard) {
|
||||
|
|
@ -189,8 +189,8 @@ public class CardInfo {
|
|||
List<String> manaCostLeft = ((ModalDoubleFacedCard) card).getLeftHalfCard().getManaCostSymbols();
|
||||
List<String> manaCostRight = ((ModalDoubleFacedCard) card).getRightHalfCard().getManaCostSymbols();
|
||||
this.setManaCosts(CardUtil.concatManaSymbols(SPLIT_MANA_SEPARATOR_FULL, manaCostLeft, manaCostRight));
|
||||
} else if (card instanceof AdventureCard) {
|
||||
List<String> manaCostLeft = ((AdventureCard) card).getSpellCard().getManaCostSymbols();
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
List<String> manaCostLeft = ((CardWithSpellOption) card).getSpellCard().getManaCostSymbols();
|
||||
List<String> manaCostRight = card.getManaCostSymbols();
|
||||
this.setManaCosts(CardUtil.concatManaSymbols(SPLIT_MANA_SEPARATOR_FULL, manaCostLeft, manaCostRight));
|
||||
} else {
|
||||
|
|
@ -469,12 +469,16 @@ public class CardInfo {
|
|||
return secondSideName;
|
||||
}
|
||||
|
||||
public boolean isAdventureCard() {
|
||||
return adventureCard;
|
||||
public boolean isCardWithSpellOption() {
|
||||
return cardWithSpellOption;
|
||||
}
|
||||
|
||||
public String getAdventureSpellName() {
|
||||
return adventureSpellName;
|
||||
/**
|
||||
* used for spell card portion of adventure/omen cards
|
||||
* @return name of the spell
|
||||
*/
|
||||
public String getSpellOptionCardName() {
|
||||
return spellOptionCardName;
|
||||
}
|
||||
|
||||
public boolean isModalDoubleFacedCard() {
|
||||
|
|
|
|||
|
|
@ -147,8 +147,8 @@ public enum CardRepository {
|
|||
if (card.getMeldsToCardName() != null && !card.getMeldsToCardName().isEmpty()) {
|
||||
namesList.add(card.getMeldsToCardName());
|
||||
}
|
||||
if (card.getAdventureSpellName() != null && !card.getAdventureSpellName().isEmpty()) {
|
||||
namesList.add(card.getAdventureSpellName());
|
||||
if (card.getSpellOptionCardName() != null && !card.getSpellOptionCardName().isEmpty()) {
|
||||
namesList.add(card.getSpellOptionCardName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
List<CardInfo> results = cardsDao.query(qb.prepare());
|
||||
for (CardInfo card : results) {
|
||||
addNewNames(card, names);
|
||||
|
|
@ -176,7 +176,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
qb.where().not().like("types", new SelectArg('%' + CardType.LAND.name() + '%'));
|
||||
List<CardInfo> results = cardsDao.query(qb.prepare());
|
||||
for (CardInfo card : results) {
|
||||
|
|
@ -193,7 +193,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
Where<CardInfo, Object> where = qb.where();
|
||||
where.and(
|
||||
where.not().like("supertypes", '%' + SuperType.BASIC.name() + '%'),
|
||||
|
|
@ -214,7 +214,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
qb.where().not().like("supertypes", new SelectArg('%' + SuperType.BASIC.name() + '%'));
|
||||
List<CardInfo> results = cardsDao.query(qb.prepare());
|
||||
for (CardInfo card : results) {
|
||||
|
|
@ -231,7 +231,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
qb.where().like("types", new SelectArg('%' + CardType.CREATURE.name() + '%'));
|
||||
List<CardInfo> results = cardsDao.query(qb.prepare());
|
||||
for (CardInfo card : results) {
|
||||
|
|
@ -248,7 +248,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
qb.where().like("types", new SelectArg('%' + CardType.ARTIFACT.name() + '%'));
|
||||
List<CardInfo> results = cardsDao.query(qb.prepare());
|
||||
for (CardInfo card : results) {
|
||||
|
|
@ -265,7 +265,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
Where<CardInfo, Object> where = qb.where();
|
||||
where.and(
|
||||
where.not().like("types", '%' + CardType.CREATURE.name() + '%'),
|
||||
|
|
@ -286,7 +286,7 @@ public enum CardRepository {
|
|||
Set<String> names = new TreeSet<>();
|
||||
try {
|
||||
QueryBuilder<CardInfo, Object> qb = cardsDao.queryBuilder();
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "adventureSpellName");
|
||||
qb.distinct().selectColumns("name", "modalDoubleFacedSecondSideName", "secondSideName", "flipCardName", "spellOptionCardName");
|
||||
Where<CardInfo, Object> where = qb.where();
|
||||
where.and(
|
||||
where.not().like("types", '%' + CardType.ARTIFACT.name() + '%'),
|
||||
|
|
@ -511,7 +511,7 @@ public enum CardRepository {
|
|||
queryBuilder.where()
|
||||
.eq("flipCardName", new SelectArg(name)).or()
|
||||
.eq("secondSideName", new SelectArg(name)).or()
|
||||
.eq("adventureSpellName", new SelectArg(name)).or()
|
||||
.eq("spellOptionCardName", new SelectArg(name)).or()
|
||||
.eq("modalDoubleFacedSecondSideName", new SelectArg(name));
|
||||
results = cardsDao.query(queryBuilder.prepare());
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ public enum SpellAbilityType {
|
|||
MODAL_LEFT("LeftModal SpellAbility"),
|
||||
MODAL_RIGHT("RightModal SpellAbility"),
|
||||
SPLICE("Spliced SpellAbility"),
|
||||
ADVENTURE_SPELL("Adventure SpellAbility");
|
||||
ADVENTURE_SPELL("Adventure SpellAbility"),
|
||||
OMEN_SPELL("Omen SpellAbility");
|
||||
|
||||
private final String text;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public enum SubType {
|
|||
ADVENTURE("Adventure", SubTypeSet.SpellType),
|
||||
ARCANE("Arcane", SubTypeSet.SpellType),
|
||||
LESSON("Lesson", SubTypeSet.SpellType),
|
||||
OMEN("Omen", SubTypeSet.SpellType),
|
||||
TRAP("Trap", SubTypeSet.SpellType),
|
||||
|
||||
// Battle subtypes
|
||||
|
|
@ -274,6 +275,7 @@ public enum SubType {
|
|||
MONGOOSE("Mongoose", SubTypeSet.CreatureType),
|
||||
MONK("Monk", SubTypeSet.CreatureType),
|
||||
MONKEY("Monkey", SubTypeSet.CreatureType),
|
||||
MOOGLE("Moogle", SubTypeSet.CreatureType),
|
||||
MOONFOLK("Moonfolk", SubTypeSet.CreatureType),
|
||||
MOUNT("Mount", SubTypeSet.CreatureType),
|
||||
MOUSE("Mouse", SubTypeSet.CreatureType),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package mage.filter.predicate.card;
|
||||
|
||||
import mage.cards.AdventureCard;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.ModalDoubleFacedCard;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.*;
|
||||
import mage.cards.mock.MockCard;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
|
|
@ -55,8 +52,8 @@ public class CardTextPredicate implements Predicate<Card> {
|
|||
fullName = ((MockCard) input).getFullName(true);
|
||||
} else if (input instanceof ModalDoubleFacedCard) {
|
||||
fullName = input.getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + ((ModalDoubleFacedCard) input).getRightHalfCard().getName();
|
||||
} else if (input instanceof AdventureCard) {
|
||||
fullName = input.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + ((AdventureCard) input).getSpellCard().getName();
|
||||
} else if (input instanceof CardWithSpellOption) {
|
||||
fullName = input.getName() + MockCard.CARD_WITH_SPELL_OPTION_NAME_SEPARATOR + ((CardWithSpellOption) input).getSpellCard().getName();
|
||||
}
|
||||
|
||||
if (fullName.toLowerCase(Locale.ENGLISH).contains(text.toLowerCase(Locale.ENGLISH))) {
|
||||
|
|
@ -107,8 +104,8 @@ public class CardTextPredicate implements Predicate<Card> {
|
|||
}
|
||||
}
|
||||
|
||||
if (input instanceof AdventureCard) {
|
||||
for (String rule : ((AdventureCard) input).getSpellCard().getRules(game)) {
|
||||
if (input instanceof CardWithSpellOption) {
|
||||
for (String rule : ((CardWithSpellOption) input).getSpellCard().getRules(game)) {
|
||||
if (rule.toLowerCase(Locale.ENGLISH).contains(token)) {
|
||||
found = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -334,8 +334,8 @@ public abstract class GameImpl implements Game {
|
|||
Card rightCard = ((ModalDoubleFacedCard) card).getRightHalfCard();
|
||||
rightCard.setOwnerId(ownerId);
|
||||
addCardToState(rightCard);
|
||||
} else if (card instanceof AdventureCard) {
|
||||
Card spellCard = ((AdventureCard) card).getSpellCard();
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
Card spellCard = ((CardWithSpellOption) card).getSpellCard();
|
||||
spellCard.setOwnerId(ownerId);
|
||||
addCardToState(spellCard);
|
||||
} else if (card.isTransformable() && card.getSecondCardFace() != null) {
|
||||
|
|
|
|||
|
|
@ -1639,14 +1639,14 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
copiedParts.add(rightCopied);
|
||||
// sync parts
|
||||
((ModalDoubleFacedCard) copiedCard).setParts(leftCopied, rightCopied);
|
||||
} else if (copiedCard instanceof AdventureCard) {
|
||||
} else if (copiedCard instanceof CardWithSpellOption) {
|
||||
// right
|
||||
AdventureCardSpell rightOriginal = ((AdventureCard) copiedCard).getSpellCard();
|
||||
AdventureCardSpell rightCopied = rightOriginal.copy();
|
||||
SpellOptionCard rightOriginal = ((CardWithSpellOption) copiedCard).getSpellCard();
|
||||
SpellOptionCard rightCopied = rightOriginal.copy();
|
||||
prepareCardForCopy(rightOriginal, rightCopied, newController);
|
||||
copiedParts.add(rightCopied);
|
||||
// sync parts
|
||||
((AdventureCard) copiedCard).setParts(rightCopied);
|
||||
((CardWithSpellOption) copiedCard).setParts(rightCopied);
|
||||
}
|
||||
|
||||
// main part prepare (must be called after other parts cause it change ids for all)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.PreventDamageToSourceEffect;
|
||||
import mage.abilities.keyword.VanishingAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
|
||||
/**
|
||||
* @author padfoothelix
|
||||
*/
|
||||
public final class AlienRhinoToken extends TokenImpl {
|
||||
|
||||
public AlienRhinoToken() {
|
||||
super("Alien Rhino Token", "4/4 white Alien Rhino creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
subtype.add(SubType.ALIEN);
|
||||
subtype.add(SubType.RHINO);
|
||||
power = new MageInt(4);
|
||||
toughness = new MageInt(4);
|
||||
}
|
||||
|
||||
private AlienRhinoToken(final AlienRhinoToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlienRhinoToken copy() {
|
||||
return new AlienRhinoToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class CrushOfTentaclesToken extends TokenImpl {
|
||||
|
||||
public CrushOfTentaclesToken() {
|
||||
super("Octopus Token", "8/8 blue Octopus creature");
|
||||
this.cardType.add(CardType.CREATURE);
|
||||
this.color.setBlue(true);
|
||||
this.subtype.add(SubType.OCTOPUS);
|
||||
this.power = new MageInt(8);
|
||||
this.toughness = new MageInt(8);
|
||||
}
|
||||
|
||||
private CrushOfTentaclesToken(final CrushOfTentaclesToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public CrushOfTentaclesToken copy() {
|
||||
return new CrushOfTentaclesToken(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import mage.constants.SubType;
|
|||
public final class DinDragonToken extends TokenImpl {
|
||||
|
||||
public DinDragonToken() {
|
||||
super("Dragon Token", "4/4 red Dinosaur Dragon creature token with flying");
|
||||
super("Dinosaur Dragon Token", "4/4 red Dinosaur Dragon creature token with flying");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setRed(true);
|
||||
subtype.add(SubType.DINOSAUR);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import mage.constants.SubType;
|
|||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class EyesOfTheWisentElementalToken extends TokenImpl {
|
||||
public final class Elemental44GreenToken extends TokenImpl {
|
||||
|
||||
public EyesOfTheWisentElementalToken() {
|
||||
public Elemental44GreenToken() {
|
||||
super("Elemental Token", "4/4 green Elemental creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
|
|
@ -18,11 +18,11 @@ public final class EyesOfTheWisentElementalToken extends TokenImpl {
|
|||
toughness = new MageInt(4);
|
||||
}
|
||||
|
||||
private EyesOfTheWisentElementalToken(final EyesOfTheWisentElementalToken token) {
|
||||
private Elemental44GreenToken(final Elemental44GreenToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public EyesOfTheWisentElementalToken copy() {
|
||||
return new EyesOfTheWisentElementalToken(this);
|
||||
public Elemental44GreenToken copy() {
|
||||
return new Elemental44GreenToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,13 +7,13 @@ import mage.constants.SubType;
|
|||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class SeedGuardianToken extends TokenImpl {
|
||||
public final class ElementalXXGreenToken extends TokenImpl {
|
||||
|
||||
public SeedGuardianToken() {
|
||||
public ElementalXXGreenToken() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public SeedGuardianToken(int xValue) {
|
||||
public ElementalXXGreenToken(int xValue) {
|
||||
super("Elemental Token", "X/X green Elemental creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
|
|
@ -22,11 +22,11 @@ public final class SeedGuardianToken extends TokenImpl {
|
|||
toughness = new MageInt(xValue);
|
||||
}
|
||||
|
||||
private SeedGuardianToken(final SeedGuardianToken token) {
|
||||
private ElementalXXGreenToken(final ElementalXXGreenToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public SeedGuardianToken copy() {
|
||||
return new SeedGuardianToken(this);
|
||||
public ElementalXXGreenToken copy() {
|
||||
return new ElementalXXGreenToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class GrovetenderDruidsPlantToken extends TokenImpl {
|
||||
|
||||
public GrovetenderDruidsPlantToken() {
|
||||
super("Plant Token", "1/1 green Plant creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
subtype.add(SubType.PLANT);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
}
|
||||
|
||||
private GrovetenderDruidsPlantToken(final GrovetenderDruidsPlantToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public GrovetenderDruidsPlantToken copy() {
|
||||
return new GrovetenderDruidsPlantToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,13 +7,13 @@ import mage.constants.SubType;
|
|||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class FleshCarverHorrorToken extends TokenImpl {
|
||||
public final class HorrorXXBlackToken extends TokenImpl {
|
||||
|
||||
public FleshCarverHorrorToken() {
|
||||
public HorrorXXBlackToken() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public FleshCarverHorrorToken(int xValue) {
|
||||
public HorrorXXBlackToken(int xValue) {
|
||||
super("Horror Token", "X/X black Horror creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setBlack(true);
|
||||
|
|
@ -22,11 +22,11 @@ public final class FleshCarverHorrorToken extends TokenImpl {
|
|||
toughness = new MageInt(xValue);
|
||||
}
|
||||
|
||||
private FleshCarverHorrorToken(final FleshCarverHorrorToken token) {
|
||||
private HorrorXXBlackToken(final HorrorXXBlackToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public FleshCarverHorrorToken copy() {
|
||||
return new FleshCarverHorrorToken(this);
|
||||
public HorrorXXBlackToken copy() {
|
||||
return new HorrorXXBlackToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
|
||||
/**
|
||||
* @author padfoothelix
|
||||
*/
|
||||
public final class Human11WithWard2Token extends TokenImpl {
|
||||
|
||||
public Human11WithWard2Token() {
|
||||
super("Human Token", "1/1 white Human creature token with ward {2}");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
subtype.add(SubType.HUMAN);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
this.addAbility(new WardAbility(new GenericManaCost(2)));
|
||||
}
|
||||
|
||||
private Human11WithWard2Token(final Human11WithWard2Token token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Human11WithWard2Token copy() {
|
||||
return new Human11WithWard2Token(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import mage.constants.SubType;
|
|||
public final class HumanRogueToken extends TokenImpl {
|
||||
|
||||
public HumanRogueToken() {
|
||||
super("Human Token", "1/1 white Human Rogue creature token");
|
||||
super("Human Rogue Token", "1/1 white Human Rogue creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
subtype.add(SubType.HUMAN);
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
|
||||
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.MageInt;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class MarathWillOfTheWildElementalToken extends TokenImpl {
|
||||
|
||||
public MarathWillOfTheWildElementalToken() {
|
||||
super("Elemental Token", "X/X green Elemental creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.ELEMENTAL);
|
||||
color.setGreen(true);
|
||||
power = new MageInt(0);
|
||||
toughness = new MageInt(0);
|
||||
}
|
||||
|
||||
private MarathWillOfTheWildElementalToken(final MarathWillOfTheWildElementalToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public MarathWillOfTheWildElementalToken copy() {
|
||||
return new MarathWillOfTheWildElementalToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,25 +5,20 @@ import mage.constants.CardType;
|
|||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author FenrisulfrX
|
||||
* @author Quercitron
|
||||
*/
|
||||
public final class MinionToken extends TokenImpl {
|
||||
|
||||
public MinionToken() {
|
||||
this("DDE");
|
||||
}
|
||||
|
||||
public MinionToken(String setCode) {
|
||||
super("Phyrexian Minion Token", "X/X black Phyrexian Minion creature token");
|
||||
super("Minion Token", "1/1 black Minion creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.PHYREXIAN);
|
||||
subtype.add(SubType.MINION);
|
||||
color.setBlack(true);
|
||||
power = new MageInt(0);
|
||||
toughness = new MageInt(0);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
}
|
||||
|
||||
private MinionToken(final MinionToken token) {
|
||||
protected MinionToken(final MinionToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author Quercitron
|
||||
*/
|
||||
public final class MinionToken2 extends TokenImpl {
|
||||
|
||||
public MinionToken2() {
|
||||
super("Minion Token", "1/1 black Minion creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.MINION);
|
||||
color.setBlack(true);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
}
|
||||
|
||||
protected MinionToken2(final MinionToken2 token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public MinionToken2 copy() {
|
||||
return new MinionToken2(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
|
||||
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class NighteyesTheDesecratorToken extends TokenImpl {
|
||||
|
||||
public NighteyesTheDesecratorToken() {
|
||||
super("Nighteyes the Desecrator Token", "");
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setBlack(true);
|
||||
subtype.add(SubType.RAT);
|
||||
subtype.add(SubType.WIZARD);
|
||||
power = new MageInt(4);
|
||||
toughness = new MageInt(2);
|
||||
// {4}{B}: Put target creature card from a graveyard onto the battlefield under your control.
|
||||
Ability ability = new SimpleActivatedAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl<>("{4}{B}"));
|
||||
ability.addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE_A_GRAVEYARD));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private NighteyesTheDesecratorToken(final NighteyesTheDesecratorToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public NighteyesTheDesecratorToken copy() {
|
||||
return new NighteyesTheDesecratorToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author FenrisulfrX
|
||||
*/
|
||||
public final class PhyrexianMinionToken extends TokenImpl {
|
||||
|
||||
public PhyrexianMinionToken() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public PhyrexianMinionToken(int xValue) {
|
||||
super("Phyrexian Minion Token", "X/X black Phyrexian Minion creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.PHYREXIAN);
|
||||
subtype.add(SubType.MINION);
|
||||
color.setBlack(true);
|
||||
power = new MageInt(xValue);
|
||||
toughness = new MageInt(xValue);
|
||||
}
|
||||
|
||||
private PhyrexianMinionToken(final PhyrexianMinionToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public PhyrexianMinionToken copy() {
|
||||
return new PhyrexianMinionToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,9 +4,12 @@ import mage.MageInt;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
public final class GrismoldPlantToken extends TokenImpl {
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class Plant11Token extends TokenImpl {
|
||||
|
||||
public GrismoldPlantToken() {
|
||||
public Plant11Token() {
|
||||
super("Plant Token", "1/1 green Plant creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
|
|
@ -15,11 +18,11 @@ public final class GrismoldPlantToken extends TokenImpl {
|
|||
toughness = new MageInt(1);
|
||||
}
|
||||
|
||||
private GrismoldPlantToken(final GrismoldPlantToken token) {
|
||||
private Plant11Token(final Plant11Token token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public GrismoldPlantToken copy() {
|
||||
return new GrismoldPlantToken(this);
|
||||
public Plant11Token copy() {
|
||||
return new Plant11Token(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.MageInt;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class RallyTheHordeWarriorToken extends TokenImpl {
|
||||
|
||||
public RallyTheHordeWarriorToken() {
|
||||
super("Warrior Token", "1/1 red Warrior creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setRed(true);
|
||||
subtype.add(SubType.WARRIOR);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
}
|
||||
|
||||
private RallyTheHordeWarriorToken(final RallyTheHordeWarriorToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public RallyTheHordeWarriorToken copy() {
|
||||
return new RallyTheHordeWarriorToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class SorinSolemnVisitorVampireToken extends TokenImpl {
|
||||
|
||||
public SorinSolemnVisitorVampireToken() {
|
||||
super("Vampire Token", "2/2 black Vampire creature token with flying");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setBlack(true);
|
||||
subtype.add(SubType.VAMPIRE);
|
||||
power = new MageInt(2);
|
||||
toughness = new MageInt(2);
|
||||
addAbility(FlyingAbility.getInstance());
|
||||
}
|
||||
|
||||
private SorinSolemnVisitorVampireToken(final SorinSolemnVisitorVampireToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public SorinSolemnVisitorVampireToken copy() {
|
||||
return new SorinSolemnVisitorVampireToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public final class SpoilsOfBloodHorrorToken extends TokenImpl {
|
||||
|
||||
public SpoilsOfBloodHorrorToken() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public SpoilsOfBloodHorrorToken(int xValue) {
|
||||
super("Horror Token", "X/X black Horror creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setBlack(true);
|
||||
subtype.add(SubType.HORROR);
|
||||
power = new MageInt(xValue);
|
||||
toughness = new MageInt(xValue);
|
||||
}
|
||||
|
||||
private SpoilsOfBloodHorrorToken(final SpoilsOfBloodHorrorToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public SpoilsOfBloodHorrorToken copy() {
|
||||
return new SpoilsOfBloodHorrorToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package mage.game.permanent.token;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
|
||||
public final class WalkerOfTheGroveToken extends TokenImpl {
|
||||
|
||||
public WalkerOfTheGroveToken() {
|
||||
super("Elemental Token", "4/4 green Elemental creature token");
|
||||
cardType.add(CardType.CREATURE);
|
||||
this.subtype.add(SubType.ELEMENTAL);
|
||||
this.color.setGreen(true);
|
||||
power = new MageInt(4);
|
||||
toughness = new MageInt(4);
|
||||
}
|
||||
|
||||
private WalkerOfTheGroveToken(final WalkerOfTheGroveToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public WalkerOfTheGroveToken copy() {
|
||||
return new WalkerOfTheGroveToken(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -209,10 +209,11 @@ public class Spell extends StackObjectImpl implements Card {
|
|||
+ " using " + this.getSpellAbility().getSpellAbilityCastMode();
|
||||
}
|
||||
|
||||
if (card instanceof AdventureCardSpell) {
|
||||
AdventureCard adventureCard = ((AdventureCardSpell) card).getParentCard();
|
||||
return GameLog.replaceNameByColoredName(card, getSpellAbility().toString(), adventureCard)
|
||||
+ " as Adventure spell of " + GameLog.getColoredObjectIdName(adventureCard);
|
||||
if (card instanceof SpellOptionCard) {
|
||||
CardWithSpellOption parentCard = ((SpellOptionCard) card).getParentCard();
|
||||
String type = ((SpellOptionCard) card).getSpellType();
|
||||
return GameLog.replaceNameByColoredName(card, getSpellAbility().toString(), parentCard)
|
||||
+ " as " + type + " spell of " + GameLog.getColoredObjectIdName(parentCard);
|
||||
}
|
||||
|
||||
if (card instanceof ModalDoubleFacedCardHalf) {
|
||||
|
|
@ -539,8 +540,8 @@ public class Spell extends StackObjectImpl implements Card {
|
|||
public String getIdName() {
|
||||
String idName;
|
||||
if (card != null) {
|
||||
if (card instanceof AdventureCardSpell) {
|
||||
idName = ((AdventureCardSpell) card).getParentCard().getId().toString().substring(0, 3);
|
||||
if (card instanceof SpellOptionCard) {
|
||||
idName = ((SpellOptionCard) card).getParentCard().getId().toString().substring(0, 3);
|
||||
} else {
|
||||
idName = card.getId().toString().substring(0, 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4068,11 +4068,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
getPlayableFromObjectSingle(game, fromZone, mainCard.getLeftHalfCard(), mainCard.getLeftHalfCard().getAbilities(game), availableMana, output);
|
||||
getPlayableFromObjectSingle(game, fromZone, mainCard.getRightHalfCard(), mainCard.getRightHalfCard().getAbilities(game), availableMana, output);
|
||||
getPlayableFromObjectSingle(game, fromZone, mainCard, mainCard.getSharedAbilities(game), availableMana, output);
|
||||
} else if (object instanceof AdventureCard) {
|
||||
} else if (object instanceof CardWithSpellOption) {
|
||||
// adventure must use different card characteristics for different spells (main or adventure)
|
||||
AdventureCard adventureCard = (AdventureCard) object;
|
||||
getPlayableFromObjectSingle(game, fromZone, adventureCard.getSpellCard(), adventureCard.getSpellCard().getAbilities(game), availableMana, output);
|
||||
getPlayableFromObjectSingle(game, fromZone, adventureCard, adventureCard.getSharedAbilities(game), availableMana, output);
|
||||
CardWithSpellOption cardWithSpellOption = (CardWithSpellOption) object;
|
||||
getPlayableFromObjectSingle(game, fromZone, cardWithSpellOption.getSpellCard(), cardWithSpellOption.getSpellCard().getAbilities(game), availableMana, output);
|
||||
getPlayableFromObjectSingle(game, fromZone, cardWithSpellOption, cardWithSpellOption.getSharedAbilities(game), availableMana, output);
|
||||
} else if (object instanceof Card) {
|
||||
getPlayableFromObjectSingle(game, fromZone, object, ((Card) object).getAbilities(game), availableMana, output);
|
||||
} else if (object instanceof StackObject) {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public class FixedTargets extends TargetPointerImpl {
|
|||
.collect(Collectors.toList()), game);
|
||||
}
|
||||
|
||||
public FixedTargets(List<MageObjectReference> morList) {
|
||||
public FixedTargets(Collection<MageObjectReference> morList) {
|
||||
super();
|
||||
targets.addAll(morList);
|
||||
this.setInitialized(); // no need dynamic init
|
||||
|
|
|
|||
|
|
@ -1086,13 +1086,22 @@ public final class CardUtil {
|
|||
* @param game the Game from checkTrigger() or watch()
|
||||
* @return the StackObject which targeted the source, or null if not found
|
||||
*/
|
||||
public static StackObject getTargetingStackObject(GameEvent event, Game game) {
|
||||
public static StackObject getTargetingStackObject(String checkingReference, GameEvent event, Game game) {
|
||||
// In case of multiple simultaneous triggered abilities from the same source,
|
||||
// need to get the actual one that targeted, see #8026, #8378
|
||||
// Also avoids triggering on cancelled selections, see #8802
|
||||
String stateKey = "targetedMap" + checkingReference;
|
||||
Map<UUID, Set<UUID>> targetMap = (Map<UUID, Set<UUID>>) game.getState().getValue(stateKey);
|
||||
// targetMap: key - targetId; value - Set of stackObject Ids
|
||||
if (targetMap == null) {
|
||||
targetMap = new HashMap<>();
|
||||
} else {
|
||||
targetMap = new HashMap<>(targetMap); // must have new object reference if saved back to game state
|
||||
}
|
||||
Set<UUID> targetingObjects = targetMap.computeIfAbsent(event.getTargetId(), k -> new HashSet<>());
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
Ability stackAbility = stackObject.getStackAbility();
|
||||
if (stackAbility == null || !stackAbility.getSourceId().equals(event.getSourceId())) {
|
||||
if (stackAbility == null || !stackAbility.getSourceId().equals(event.getSourceId()) || targetingObjects.contains(stackObject.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (CardUtil.getAllSelectedTargets(stackAbility, game).contains(event.getTargetId())) {
|
||||
|
|
@ -1263,7 +1272,7 @@ public final class CardUtil {
|
|||
Card permCard;
|
||||
if (card instanceof SplitCard) {
|
||||
permCard = card;
|
||||
} else if (card instanceof AdventureCard) {
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
permCard = card;
|
||||
} else if (card instanceof ModalDoubleFacedCard) {
|
||||
permCard = ((ModalDoubleFacedCard) card).getLeftHalfCard();
|
||||
|
|
@ -1451,9 +1460,9 @@ public final class CardUtil {
|
|||
if (cardToCast instanceof CardWithHalves) {
|
||||
cards.add(((CardWithHalves) cardToCast).getLeftHalfCard());
|
||||
cards.add(((CardWithHalves) cardToCast).getRightHalfCard());
|
||||
} else if (cardToCast instanceof AdventureCard) {
|
||||
} else if (cardToCast instanceof CardWithSpellOption) {
|
||||
cards.add(cardToCast);
|
||||
cards.add(((AdventureCard) cardToCast).getSpellCard());
|
||||
cards.add(((CardWithSpellOption) cardToCast).getSpellCard());
|
||||
} else {
|
||||
cards.add(cardToCast);
|
||||
}
|
||||
|
|
@ -1642,9 +1651,9 @@ public final class CardUtil {
|
|||
}
|
||||
|
||||
// handle adventure cards
|
||||
if (card instanceof AdventureCard) {
|
||||
if (card instanceof CardWithSpellOption) {
|
||||
Card creatureCard = card.getMainCard();
|
||||
Card spellCard = ((AdventureCard) card).getSpellCard();
|
||||
Card spellCard = ((CardWithSpellOption) card).getSpellCard();
|
||||
if (manaCost != null) {
|
||||
// get additional cost if any
|
||||
Costs<Cost> additionalCostsCreature = creatureCard.getSpellAbility().getCosts();
|
||||
|
|
@ -1682,9 +1691,9 @@ public final class CardUtil {
|
|||
game.getState().setValue("PlayFromNotOwnHandZone" + leftHalfCard.getId(), null);
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + rightHalfCard.getId(), null);
|
||||
}
|
||||
if (card instanceof AdventureCard) {
|
||||
if (card instanceof CardWithSpellOption) {
|
||||
Card creatureCard = card.getMainCard();
|
||||
Card spellCard = ((AdventureCard) card).getSpellCard();
|
||||
Card spellCard = ((CardWithSpellOption) card).getSpellCard();
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + creatureCard.getId(), null);
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + spellCard.getId(), null);
|
||||
}
|
||||
|
|
@ -2069,8 +2078,8 @@ public final class CardUtil {
|
|||
res.add(mainCard);
|
||||
res.add(mainCard.getLeftHalfCard());
|
||||
res.add(mainCard.getRightHalfCard());
|
||||
} else if (object instanceof AdventureCard || object instanceof AdventureCardSpell) {
|
||||
AdventureCard mainCard = (AdventureCard) ((Card) object).getMainCard();
|
||||
} else if (object instanceof CardWithSpellOption || object instanceof SpellOptionCard) {
|
||||
CardWithSpellOption mainCard = (CardWithSpellOption) ((Card) object).getMainCard();
|
||||
res.add(mainCard);
|
||||
res.add(mainCard.getSpellCard());
|
||||
} else if (object instanceof Spell) {
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@ import mage.abilities.dynamicvalue.DynamicValue;
|
|||
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.AdventureCard;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.ModalDoubleFacedCard;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.*;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.ManaType;
|
||||
|
|
@ -644,8 +641,8 @@ public final class ManaUtil {
|
|||
Card secondSide;
|
||||
if (card instanceof SplitCard) {
|
||||
secondSide = ((SplitCard) card).getRightHalfCard();
|
||||
} else if (card instanceof AdventureCard) {
|
||||
secondSide = ((AdventureCard) card).getSpellCard();
|
||||
} else if (card instanceof CardWithSpellOption) {
|
||||
secondSide = ((CardWithSpellOption) card).getSpellCard();
|
||||
} else if (card instanceof ModalDoubleFacedCard) {
|
||||
secondSide = ((ModalDoubleFacedCard) card).getRightHalfCard();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class NumberOfTimesPermanentTargetedATurnWatcher extends Watcher {
|
|||
if (event.getType() != GameEvent.EventType.TARGETED) {
|
||||
return;
|
||||
}
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(event, game);
|
||||
StackObject targetingObject = CardUtil.getTargetingStackObject(this.getKey(), event, game);
|
||||
if (targetingObject == null || CardUtil.checkTargetedEventAlreadyUsed(this.getKey(), targetingObject, event, game)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue