mirror of
https://github.com/correl/mage.git
synced 2025-01-11 19:13:02 +00:00
* Fixed a problem with stack abilities created by Designations eg. Monarch triggered ability (fixes #4457).
This commit is contained in:
parent
c3934ae70b
commit
329116669a
6 changed files with 184 additions and 156 deletions
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.view;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.MageObject;
|
||||
|
@ -44,6 +45,7 @@ import mage.counters.CounterType;
|
|||
import mage.designations.Designation;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.command.Plane;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
@ -53,9 +55,6 @@ import mage.target.Target;
|
|||
import mage.target.Targets;
|
||||
import mage.util.SubTypeList;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import mage.game.command.Plane;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -529,6 +528,13 @@ public class CardView extends SimpleCardView {
|
|||
// Display in landscape/rotated/on its side
|
||||
this.rotate = true;
|
||||
this.rules = plane.getAbilities().getRules(plane.getName());
|
||||
} else if (object instanceof Designation) {
|
||||
this.mageObjectType = MageObjectType.DESIGNATION;
|
||||
Designation designation = (Designation) object;
|
||||
this.rarity = Rarity.SPECIAL;
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
// Display in landscape/rotated/on its side
|
||||
this.rules = designation.getAbilities().getRules(designation.getName());
|
||||
}
|
||||
if (this.rarity == null && object instanceof StackAbility) {
|
||||
StackAbility stackAbility = (StackAbility) object;
|
||||
|
@ -769,7 +775,7 @@ public class CardView extends SimpleCardView {
|
|||
|
||||
@Override
|
||||
public String getExpansionSetCode() {
|
||||
if (expansionSetCode == null) {
|
||||
if (expansionSetCode == null) {
|
||||
expansionSetCode = "";
|
||||
}
|
||||
return expansionSetCode;
|
||||
|
|
|
@ -149,7 +149,7 @@ public class GameView implements Serializable {
|
|||
} else if (object instanceof Designation) {
|
||||
Designation designation = (Designation) game.getObject(object.getId());
|
||||
if (designation != null) {
|
||||
stack.put(stackObject.getId(), new CardView(designation, (StackAbility) stackObject));
|
||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, designation.getName(), new CardView(designation)));
|
||||
} else {
|
||||
LOGGER.fatal("Designation object not found: " + object.getName() + ' ' + object.toString() + ' ' + object.getClass().toString());
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ import mage.target.common.TargetTriggeredAbility;
|
|||
public class StrionicResonator extends CardImpl {
|
||||
|
||||
public StrionicResonator(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
// {2}, {T}: Copy target triggered ability you control. You may choose new targets for the copy.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new StrionicResonatorEffect(), new ManaCostsImpl("{2}"));
|
||||
|
@ -89,7 +89,7 @@ class StrionicResonatorEffect extends OneShotEffect {
|
|||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (controller != null && sourcePermanent != null) {
|
||||
stackAbility.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied triggered ability").toString());
|
||||
game.informPlayers(sourcePermanent.getIdName() + ": " + controller.getLogName() + " copied triggered ability");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.abilities.effects;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
@ -37,21 +36,22 @@ import mage.game.events.GameEvent;
|
|||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public interface ReplacementEffect extends ContinuousEffect {
|
||||
|
||||
|
||||
boolean replaceEvent(GameEvent event, Ability source, Game game);
|
||||
|
||||
/**
|
||||
* This check for the relevant events is called at first to prevent further actions if
|
||||
* the current event is ignored from this effect
|
||||
* This check for the relevant events is called at first to prevent further
|
||||
* actions if the current event is ignored from this effect
|
||||
*
|
||||
* @param event
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
boolean checksEventType(GameEvent event, Game game);
|
||||
|
||||
boolean applies(GameEvent event, Ability source, Game game);
|
||||
|
||||
boolean hasSelfScope();
|
||||
|
||||
|
||||
@Override
|
||||
public ContinuousEffect copy();
|
||||
|
|
|
@ -5,42 +5,64 @@
|
|||
package mage.constants;
|
||||
|
||||
/**
|
||||
* 109.1. An object is an ability on the stack, a card, a copy of a card, a token, a spell, a permanent, or an emblem.
|
||||
* 109.2. If a spell or ability uses a description of an object that includes a card type
|
||||
* or subtype, but doesn't include the word "card," "spell," "source," or "scheme," it
|
||||
* means a permanent of that card type or subtype on the battlefield.
|
||||
* 109.2a If a spell or ability uses a description of an object that includes the word "card" and the name of a zone, it means a card matching that description in the stated zone. #
|
||||
* 109.2b If a spell or ability uses a description of an object that includes the word "spell," it means a spell matching that description on the stack. #
|
||||
* 109.2c If a spell or ability uses a description of an object that includes the word "source," it means a source matching that description -- either a source of an ability or a source of damage -- in any zone. See rule 609.7. #
|
||||
* 109.2d If an ability of a scheme card includes the text "this scheme," it means the scheme card in the command zone on which that ability is printed. #
|
||||
* 109.3. An object's characteristics are name, mana cost, color, color indicator, card type, subtype, supertype, expansion symbol, rules text, abilities, power, toughness, loyalty, hand modifier, and life modifier. Objects can have some or all of these characteristics. Any other information about an object isn't a characteristic. For example, characteristics don't include whether a permanent is tapped, a spell's target, an object's owner or controller, what an Aura enchants, and so on. #
|
||||
* 109.4. Only objects on the stack or on the battlefield have a controller. Objects that are neither on the stack nor on the battlefield aren't controlled by any player. See rule 108.4. There are four exceptions to this rule: #
|
||||
* 109.4a An emblem is controlled by the player that puts it into the command zone. See rule 113, "Emblems." #
|
||||
* 109.4b In a Planechase game, a face-up plane or phenomenon card is controlled by the player designated as the planar controller. This is usually the active player. See rule 901.6. #
|
||||
* 109.4c In a Vanguard game, each vanguard card is controlled by its owner. See rule 902.6. #
|
||||
* 109.4d In an Archenemy game, each scheme card is controlled by its owner. See rule 904.7. #
|
||||
* 109.5. The words "you" and "your" on an object refer to the object's controller, its would-be controller (if a player is attempting to play, cast, or activate it), or its owner (if it has no controller). For a static ability, this is the current controller of the object it's on. For an activated ability, this is the player who activated the ability. For a triggered ability, this is the controller of the object when the ability triggered, unless it's a delayed triggered ability. To determine the controller of a delayed triggered ability, see rules 603.7d-f
|
||||
* 109.1. An object is an ability on the stack, a card, a copy of a card, a
|
||||
* token, a spell, a permanent, or an emblem. 109.2. If a spell or ability uses
|
||||
* a description of an object that includes a card type or subtype, but doesn't
|
||||
* include the word "card," "spell," "source," or "scheme," it means a permanent
|
||||
* of that card type or subtype on the battlefield. 109.2a If a spell or ability
|
||||
* uses a description of an object that includes the word "card" and the name of
|
||||
* a zone, it means a card matching that description in the stated zone. #
|
||||
* 109.2b If a spell or ability uses a description of an object that includes
|
||||
* the word "spell," it means a spell matching that description on the stack. #
|
||||
* 109.2c If a spell or ability uses a description of an object that includes
|
||||
* the word "source," it means a source matching that description -- either a
|
||||
* source of an ability or a source of damage -- in any zone. See rule 609.7. #
|
||||
* 109.2d If an ability of a scheme card includes the text "this scheme," it
|
||||
* means the scheme card in the command zone on which that ability is printed. #
|
||||
* 109.3. An object's characteristics are name, mana cost, color, color
|
||||
* indicator, card type, subtype, supertype, expansion symbol, rules text,
|
||||
* abilities, power, toughness, loyalty, hand modifier, and life modifier.
|
||||
* Objects can have some or all of these characteristics. Any other information
|
||||
* about an object isn't a characteristic. For example, characteristics don't
|
||||
* include whether a permanent is tapped, a spell's target, an object's owner or
|
||||
* controller, what an Aura enchants, and so on. # 109.4. Only objects on the
|
||||
* stack or on the battlefield have a controller. Objects that are neither on
|
||||
* the stack nor on the battlefield aren't controlled by any player. See rule
|
||||
* 108.4. There are four exceptions to this rule: # 109.4a An emblem is
|
||||
* controlled by the player that puts it into the command zone. See rule 113,
|
||||
* "Emblems." # 109.4b In a Planechase game, a face-up plane or phenomenon card
|
||||
* is controlled by the player designated as the planar controller. This is
|
||||
* usually the active player. See rule 901.6. # 109.4c In a Vanguard game, each
|
||||
* vanguard card is controlled by its owner. See rule 902.6. # 109.4d In an
|
||||
* Archenemy game, each scheme card is controlled by its owner. See rule 904.7.
|
||||
* # 109.5. The words "you" and "your" on an object refer to the object's
|
||||
* controller, its would-be controller (if a player is attempting to play, cast,
|
||||
* or activate it), or its owner (if it has no controller). For a static
|
||||
* ability, this is the current controller of the object it's on. For an
|
||||
* activated ability, this is the player who activated the ability. For a
|
||||
* triggered ability, this is the controller of the object when the ability
|
||||
* triggered, unless it's a delayed triggered ability. To determine the
|
||||
* controller of a delayed triggered ability, see rules 603.7d-f
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public enum MageObjectType {
|
||||
ABILITY_STACK ("Ability on the Stack", false, false),
|
||||
CARD ("Card", false, true),
|
||||
COPY_CARD ("Copy of a Card", false, true),
|
||||
TOKEN ("Token", true, true),
|
||||
SPELL ("Spell", false, true),
|
||||
PERMANENT ("Permanent", true, true),
|
||||
EMBLEM ("Emblem", false, false),
|
||||
COMMANDER ("Commander", false, false),
|
||||
PLANE ("Plane", false, false),
|
||||
ABILITY_STACK("Ability on the Stack", false, false),
|
||||
CARD("Card", false, true),
|
||||
COPY_CARD("Copy of a Card", false, true),
|
||||
TOKEN("Token", true, true),
|
||||
SPELL("Spell", false, true),
|
||||
PERMANENT("Permanent", true, true),
|
||||
EMBLEM("Emblem", false, false),
|
||||
COMMANDER("Commander", false, false),
|
||||
DESIGNATION("Designation", false, false),
|
||||
PLANE("Plane", false, false),
|
||||
NULL("NullObject", false, false);
|
||||
|
||||
private final String text;
|
||||
private final boolean permanent;
|
||||
private final boolean canHaveCounters;
|
||||
|
||||
|
||||
MageObjectType(String text, boolean permanent, boolean canHaveCounters) {
|
||||
this.text = text;
|
||||
this.permanent = permanent;
|
||||
|
|
|
@ -1,117 +1,117 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.TargetObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class TargetTriggeredAbility extends TargetObject {
|
||||
|
||||
public TargetTriggeredAbility() {
|
||||
this.minNumberOfTargets = 1;
|
||||
this.maxNumberOfTargets = 1;
|
||||
this.zone = Zone.STACK;
|
||||
this.targetName = "target triggered ability you control";
|
||||
}
|
||||
|
||||
public TargetTriggeredAbility(final TargetTriggeredAbility target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
if (source != null && source.getSourceId().equals(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StackObject stackObject = game.getStack().getStackObject(id);
|
||||
return stackObject.getStackAbility() != null
|
||||
&& (stackObject.getStackAbility() instanceof TriggeredAbility)
|
||||
&& source != null
|
||||
&& stackObject.getStackAbility().getControllerId().equals(source.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
return canChoose(sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject.getStackAbility() != null
|
||||
&& stackObject.getStackAbility() instanceof TriggeredAbility
|
||||
&& stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
return possibleTargets(sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject.getStackAbility() != null
|
||||
&& stackObject.getStackAbility() instanceof TriggeredAbility
|
||||
&& stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) {
|
||||
possibleTargets.add(stackObject.getStackAbility().getId());
|
||||
}
|
||||
}
|
||||
return possibleTargets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetTriggeredAbility copy() {
|
||||
return new TargetTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return new FilterAbility();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.TargetObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public class TargetTriggeredAbility extends TargetObject {
|
||||
|
||||
public TargetTriggeredAbility() {
|
||||
this.minNumberOfTargets = 1;
|
||||
this.maxNumberOfTargets = 1;
|
||||
this.zone = Zone.STACK;
|
||||
this.targetName = "target triggered ability you control";
|
||||
}
|
||||
|
||||
public TargetTriggeredAbility(final TargetTriggeredAbility target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
||||
if (source != null && source.getSourceId().equals(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StackObject stackObject = game.getStack().getStackObject(id);
|
||||
return stackObject.getStackAbility() != null
|
||||
&& (stackObject.getStackAbility() instanceof TriggeredAbility)
|
||||
&& source != null
|
||||
&& stackObject.getStackAbility().getControllerId().equals(source.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
return canChoose(sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject.getStackAbility() != null
|
||||
&& stackObject.getStackAbility() instanceof TriggeredAbility
|
||||
&& stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||
return possibleTargets(sourceControllerId, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject.getStackAbility() != null
|
||||
&& stackObject.getStackAbility() instanceof TriggeredAbility
|
||||
&& stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) {
|
||||
possibleTargets.add(stackObject.getStackAbility().getId());
|
||||
}
|
||||
}
|
||||
return possibleTargets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetTriggeredAbility copy() {
|
||||
return new TargetTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return new FilterAbility();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue