mirror of
https://github.com/magefree/mage.git
synced 2025-12-26 05:22:02 -08:00
Begin implementing adventures.
This commit is contained in:
parent
b0c01da007
commit
04a4b91a59
39 changed files with 495 additions and 69 deletions
|
|
@ -0,0 +1,98 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.MageSingleton;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.AdventureCard;
|
||||
import mage.cards.AdventureCardSpell;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author phulin
|
||||
*/
|
||||
public class ExileAdventureSpellEffect extends OneShotEffect implements MageSingleton {
|
||||
|
||||
private static final ExileAdventureSpellEffect instance = new ExileAdventureSpellEffect();
|
||||
|
||||
public static ExileAdventureSpellEffect getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ExileAdventureSpellEffect() {
|
||||
super(Outcome.Exile);
|
||||
staticText = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExileAdventureSpellEffect copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Spell spell = game.getStack().getSpell(source.getId());
|
||||
if (spell != null && !spell.isCopy()) {
|
||||
Card spellCard = spell.getCard();
|
||||
if (spellCard != null && spellCard instanceof AdventureCardSpell) {
|
||||
AdventureCardSpell adventureSpellCard = (AdventureCardSpell) spellCard;
|
||||
if (controller.moveCards(adventureSpellCard, Zone.EXILED, source, game)) {
|
||||
ContinuousEffect effect = new AdventureCastFromExileEffect();
|
||||
effect.setTargetPointer(new FixedTarget(adventureSpellCard.getParentCard().getId(), game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class AdventureCastFromExileEffect extends AsThoughEffectImpl {
|
||||
|
||||
public AdventureCastFromExileEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "Then exile this card. You may cast the creature later from exile.";
|
||||
}
|
||||
|
||||
public AdventureCastFromExileEffect(final AdventureCastFromExileEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdventureCastFromExileEffect copy() {
|
||||
return new AdventureCastFromExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||
if (targetId == null) {
|
||||
this.discard();
|
||||
} else if (objectId.equals(targetId)
|
||||
&& affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(objectId);
|
||||
return card != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 702.32. Flashback
|
||||
*
|
||||
* 702.32a. Flashback appears on some instants and sorceries. It represents two
|
||||
* static abilities: one that functions while the card is in a player‘s
|
||||
* graveyard and the other that functions while the card is on the stack.
|
||||
* Flashback [cost] means, "You may cast this card from your graveyard by paying
|
||||
* [cost] rather than paying its mana cost" and, "If the flashback cost was
|
||||
* paid, exile this card instead of putting it anywhere else any time it would
|
||||
* leave the stack." Casting a spell using its flashback ability follows the
|
||||
* rules for paying alternative costs in rules 601.2b and 601.2e–g.
|
||||
*
|
||||
* @author phulin
|
||||
*/
|
||||
public class AdventureCreatureAbility extends SpellAbility {
|
||||
|
||||
private String abilityName;
|
||||
private SpellAbility spellAbilityToResolve;
|
||||
|
||||
public AdventureCreatureAbility(Cost cost) {
|
||||
super(null, "", Zone.EXILED, SpellAbilityType.BASE, SpellAbilityCastMode.NORMAL);
|
||||
this.setAdditionalCostsRuleVisible(false);
|
||||
this.name = "Cast creature " + cost.getText();
|
||||
this.addCost(cost);
|
||||
this.timing = TimingRule.SORCERY;
|
||||
}
|
||||
|
||||
public AdventureCreatureAbility(final AdventureCreatureAbility ability) {
|
||||
super(ability);
|
||||
this.spellAbilityType = ability.spellAbilityType;
|
||||
this.abilityName = ability.abilityName;
|
||||
this.spellAbilityToResolve = ability.spellAbilityToResolve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivationStatus canActivate(UUID playerId, Game game) {
|
||||
if (super.canActivate(playerId, game).canActivate()) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
// Card must be in the exile zone, and it must have been cast as an adventure.
|
||||
if (game.getState().getZone(card.getId()) != Zone.EXILED) {
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
// FIXME: Make sure it was cast as an adventure.
|
||||
return card.getSpellAbility().canActivate(playerId, game);
|
||||
}
|
||||
}
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Costs<Cost> getCosts() {
|
||||
if (spellAbilityToResolve == null) {
|
||||
return super.getCosts();
|
||||
}
|
||||
return spellAbilityToResolve.getCosts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdventureCreatureAbility copy() {
|
||||
return new AdventureCreatureAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule(boolean all) {
|
||||
return this.getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sbRule = new StringBuilder("Cast from Adventure");
|
||||
/*if (!costs.isEmpty()) {
|
||||
sbRule.append("—");
|
||||
} else {
|
||||
sbRule.append(' ');
|
||||
}
|
||||
if (!manaCosts.isEmpty()) {
|
||||
sbRule.append(manaCosts.getText());
|
||||
}
|
||||
if (!costs.isEmpty()) {
|
||||
if (!manaCosts.isEmpty()) {
|
||||
sbRule.append(", ");
|
||||
}
|
||||
sbRule.append(costs.getText());
|
||||
sbRule.append('.');
|
||||
}
|
||||
if (abilityName != null) {
|
||||
sbRule.append(' ');
|
||||
sbRule.append(abilityName);
|
||||
}
|
||||
sbRule.append(" <i>(You may cast this card from your graveyard for its flashback cost. Then exile it.)</i>");*/
|
||||
return sbRule.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for split card in PlayerImpl method:
|
||||
* getOtherUseableActivatedAbilities
|
||||
*
|
||||
* @param abilityName
|
||||
*/
|
||||
public void setAbilityName(String abilityName) {
|
||||
this.abilityName = abilityName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +1,17 @@
|
|||
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.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.common.ExileAdventureSpellEffect;
|
||||
import mage.abilities.keyword.AdventureCreatureAbility;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -10,17 +19,89 @@ import java.util.UUID;
|
|||
*/
|
||||
public abstract class AdventureCard extends CardImpl {
|
||||
|
||||
protected SpellAbility adventureSpellAbility = new SpellAbility(null, null);
|
||||
/* The adventure spell card, i.e. Swift End. */
|
||||
protected Card spellCard;
|
||||
/* The ability to cast the creature from exile. */
|
||||
protected SpellAbility adventureCreatureAbility;
|
||||
|
||||
public AdventureCard(UUID ownerId, CardSetInfo setInfo, CardType[] typesLeft, CardType[] typesRight, String costsLeft, String adventureName, String costsRight) {
|
||||
super(ownerId, setInfo, typesLeft, costsLeft);
|
||||
public AdventureCard(UUID ownerId, CardSetInfo setInfo, CardType[] types, CardType[] typesSpell, String costs, String adventureName, String costsSpell) {
|
||||
super(ownerId, setInfo, types, costs);
|
||||
spellCard = new AdventureCardSpellImpl(ownerId, setInfo, typesSpell, costsSpell, this);
|
||||
spellCard.getSpellAbility().addEffect(ExileAdventureSpellEffect.getInstance());
|
||||
adventureCreatureAbility = new AdventureCreatureAbility(new ManaCostsImpl(costs));
|
||||
}
|
||||
|
||||
public AdventureCard(AdventureCard card) {
|
||||
super(card);
|
||||
this.spellCard = card.getSpellCard().copy();
|
||||
((AdventureCardSpell)this.spellCard).setParentCard(this);
|
||||
}
|
||||
|
||||
public SpellAbility getAdventureSpellAbility() {
|
||||
return adventureSpellAbility;
|
||||
public Card getSpellCard() {
|
||||
return spellCard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignNewId() {
|
||||
super.assignNewId();
|
||||
spellCard.assignNewId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) {
|
||||
game.getState().setZone(getSpellCard().getId(), toZone);
|
||||
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, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) {
|
||||
Zone currentZone = game.getState().getZone(getId());
|
||||
game.getState().setZone(getSpellCard().getId(), currentZone);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
|
||||
switch (ability.getSpellAbilityType()) {
|
||||
case ADVENTURE_SPELL:
|
||||
return this.getSpellCard().cast(game, fromZone, ability, controllerId);
|
||||
default:
|
||||
this.getSpellCard().getSpellAbility().setControllerId(controllerId);
|
||||
return super.cast(game, fromZone, ability, controllerId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities(Game game) {
|
||||
Abilities<Ability> allAbilities = new AbilitiesImpl<>();
|
||||
for (Ability ability : super.getAbilities(game)) {
|
||||
if (ability instanceof SpellAbility
|
||||
&& ((SpellAbility) ability).getSpellAbilityType() != SpellAbilityType.SPLIT
|
||||
&& ((SpellAbility) ability).getSpellAbilityType() != SpellAbilityType.SPLIT_AFTERMATH) {
|
||||
allAbilities.add(ability);
|
||||
}
|
||||
}
|
||||
allAbilities.addAll(spellCard.getAbilities(game));
|
||||
return allAbilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnerId(UUID ownerId) {
|
||||
super.setOwnerId(ownerId);
|
||||
abilities.setControllerId(ownerId);
|
||||
spellCard.getAbilities().setControllerId(ownerId);
|
||||
spellCard.setOwnerId(ownerId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
Mage/src/main/java/mage/cards/AdventureCardSpell.java
Normal file
20
Mage/src/main/java/mage/cards/AdventureCardSpell.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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.cards;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author phulin
|
||||
*/
|
||||
public interface AdventureCardSpell extends Card {
|
||||
|
||||
@Override
|
||||
AdventureCardSpell copy();
|
||||
|
||||
void setParentCard(AdventureCard card);
|
||||
|
||||
AdventureCard getParentCard();
|
||||
}
|
||||
89
Mage/src/main/java/mage/cards/AdventureCardSpellImpl.java
Normal file
89
Mage/src/main/java/mage/cards/AdventureCardSpellImpl.java
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.cards;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author phulin
|
||||
*/
|
||||
public class AdventureCardSpellImpl extends CardImpl implements AdventureCardSpell {
|
||||
|
||||
private AdventureCard adventureCardParent;
|
||||
|
||||
public AdventureCardSpellImpl(UUID ownerId, CardSetInfo setInfo, CardType[] cardTypes, String costs, AdventureCard adventureCardParent) {
|
||||
super(ownerId, setInfo, cardTypes, costs, SpellAbilityType.ADVENTURE_SPELL);
|
||||
this.adventureCardParent = adventureCardParent;
|
||||
}
|
||||
|
||||
public AdventureCardSpellImpl(final AdventureCardSpellImpl card) {
|
||||
super(card);
|
||||
this.adventureCardParent = card.adventureCardParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getOwnerId() {
|
||||
return adventureCardParent.getOwnerId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageName() {
|
||||
return adventureCardParent.getImageName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpansionSetCode() {
|
||||
return adventureCardParent.getExpansionSetCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCardNumber() {
|
||||
return adventureCardParent.getCardNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
return adventureCardParent.moveToZone(toZone, sourceId, game, flag, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
return adventureCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdventureCard getMainCard() {
|
||||
return adventureCardParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZone(Zone zone, Game game) {
|
||||
game.setZone(adventureCardParent.getId(), zone);
|
||||
game.setZone(adventureCardParent.getSpellCard().getId(), zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdventureCardSpell copy() {
|
||||
return new AdventureCardSpellImpl(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentCard(AdventureCard card) {
|
||||
this.adventureCardParent = card;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdventureCard getParentCard() {
|
||||
return this.adventureCardParent;
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ public enum SpellAbilityType {
|
|||
SPLIT_RIGHT("RightSplit SpellAbility"),
|
||||
MODE("Mode SpellAbility"),
|
||||
SPLICE("Spliced SpellAbility"),
|
||||
ADVENTURE("Adventure SpellAbility");
|
||||
ADVENTURE_SPELL("Adventure SpellAbility");
|
||||
|
||||
private final String text;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue