forked from External/mage
cleanup AbilityType for easier check that an ability is an activated ability (#12153)
* cleanup AbilityType * further cleanup * cleanup instanceof * tweak formatting * rework Rex * fix mistake in PlayerImpl * cleanup 'instanceof' for 'ActivatedManaAbilityImpl'
This commit is contained in:
parent
62cc49ffa3
commit
85cad4ff1e
118 changed files with 486 additions and 574 deletions
|
|
@ -5,7 +5,6 @@ import mage.abilities.costs.Cost;
|
|||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.abilities.mana.ManaAbility;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.util.ThreadLocalStringBuilder;
|
||||
|
|
@ -103,6 +102,11 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activated Ability in the engine are broader than in the rules.
|
||||
* Notably SpellAbility & PlayLandAbility are ActivatedAbility,
|
||||
* as they can be activated by a player (the engine meaning).
|
||||
*/
|
||||
@Override
|
||||
public Abilities<ActivatedAbility> getActivatedAbilities(Zone zone) {
|
||||
return stream()
|
||||
|
|
@ -161,7 +165,7 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
public Abilities<TriggeredAbility> getTriggeredAbilities(Zone zone) {
|
||||
Abilities<TriggeredAbility> zonedAbilities = new AbilitiesImpl<>();
|
||||
for (T ability : this) {
|
||||
if (ability instanceof TriggeredAbility && ability.getZone().match(zone)) {
|
||||
if (ability.isTriggeredAbility() && ability.getZone().match(zone)) {
|
||||
zonedAbilities.add((TriggeredAbility) ability);
|
||||
} else if (ability instanceof ZoneChangeTriggeredAbility) {
|
||||
ZoneChangeTriggeredAbility zcAbility = (ZoneChangeTriggeredAbility) ability;
|
||||
|
|
@ -176,7 +180,7 @@ public class AbilitiesImpl<T extends Ability> extends ArrayList<T> implements Ab
|
|||
@Override
|
||||
public boolean hasPoolDependantAbilities() {
|
||||
return stream()
|
||||
.filter(ability -> ability.getAbilityType() == AbilityType.MANA)
|
||||
.filter(Ability::isManaAbility)
|
||||
.map(ManaAbility.class::cast)
|
||||
.anyMatch(ManaAbility::isPoolDependant);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,31 @@ public interface Ability extends Controllable, Serializable {
|
|||
*/
|
||||
AbilityType getAbilityType();
|
||||
|
||||
/**
|
||||
* If this ability is an activated one (mana included).
|
||||
*/
|
||||
boolean isActivatedAbility();
|
||||
|
||||
/**
|
||||
* If this ability is a triggered one (mana included).
|
||||
*/
|
||||
boolean isTriggeredAbility();
|
||||
|
||||
/**
|
||||
* If this ability is an activated one, excluding mana.
|
||||
*/
|
||||
boolean isNonManaActivatedAbility();
|
||||
|
||||
/**
|
||||
* If this ability is a mana activated one.
|
||||
*/
|
||||
boolean isManaActivatedAbility();
|
||||
|
||||
/**
|
||||
* If this ability is a mana ability, (both triggered and activated can be mana abilities).
|
||||
*/
|
||||
boolean isManaAbility();
|
||||
|
||||
/**
|
||||
* Sets the id of the controller of this ability.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -162,6 +162,31 @@ public abstract class AbilityImpl implements Ability {
|
|||
return this.abilityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActivatedAbility() {
|
||||
return this.abilityType.isActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggeredAbility() {
|
||||
return this.abilityType.isTriggeredAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNonManaActivatedAbility() {
|
||||
return this.abilityType.isNonManaActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManaActivatedAbility() {
|
||||
return this.abilityType.isManaActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManaAbility() {
|
||||
return this.abilityType.isManaAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolve(Game game) {
|
||||
boolean result = true;
|
||||
|
|
@ -193,7 +218,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
boolean effectResult = effect.apply(game, this);
|
||||
result &= effectResult;
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (this.getAbilityType() != AbilityType.MANA) {
|
||||
if (!this.isManaAbility()) {
|
||||
if (!effectResult) {
|
||||
if (this.getSourceId() != null) {
|
||||
MageObject mageObject = game.getObject(this.getSourceId());
|
||||
|
|
@ -351,7 +376,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
// and/or zones become the target of a spell trigger at this point; they'll wait to be put on
|
||||
// the stack until the spell has finished being cast.)
|
||||
|
||||
if (this.getAbilityType() != AbilityType.TRIGGERED) { // triggered abilities check this already in playerImpl.triggerAbility
|
||||
if (!this.getAbilityType().isTriggeredAbility()) { // triggered abilities check this already in playerImpl.triggerAbility
|
||||
adjustTargets(game);
|
||||
}
|
||||
|
||||
|
|
@ -359,6 +384,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
Outcome outcome = getEffects().getOutcome(this);
|
||||
|
||||
// only activated abilities can be canceled by human user (not triggered)
|
||||
// Note: ActivatedAbility does include SpellAbility & PlayLandAbility, but those should be able to be canceled too.
|
||||
boolean canCancel = this instanceof ActivatedAbility && controller.isHuman();
|
||||
if (!getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, canCancel)) {
|
||||
// was canceled during targer selection
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
}
|
||||
|
||||
protected ActivatedAbilityImpl(Zone zone, Effect effect, Cost cost) {
|
||||
super(AbilityType.ACTIVATED, zone);
|
||||
super(AbilityType.ACTIVATED_NONMANA, zone);
|
||||
this.addEffect(effect);
|
||||
this.addCost(cost);
|
||||
}
|
||||
|
|
@ -147,8 +147,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
|
||||
if (approvingObjects.isEmpty()) {
|
||||
return ActivationStatus.withoutApprovingObject(true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return new ActivationStatus(approvingObjects);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
}
|
||||
|
||||
protected TriggeredAbilityImpl(Zone zone, Effect effect, boolean optional) {
|
||||
super(AbilityType.TRIGGERED, zone);
|
||||
super(AbilityType.TRIGGERED_NONMANA, zone);
|
||||
setLeavesTheBattlefieldTrigger(false);
|
||||
if (effect != null) {
|
||||
addEffect(effect);
|
||||
|
|
@ -265,6 +265,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
|
||||
/**
|
||||
* For use in generating trigger phrases with correct text
|
||||
*
|
||||
* @return "When " for an effect that always removes the source from the battlefield, otherwise "Whenever "
|
||||
*/
|
||||
protected final String getWhen() {
|
||||
|
|
|
|||
|
|
@ -54,19 +54,22 @@ public class FinalChapterAbilityResolvesTriggeredAbility extends TriggeredAbilit
|
|||
// the ID of the original ability (on the permanent) that the resolving ability
|
||||
// came from.
|
||||
Optional<Ability> ability_opt = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (!ability_opt.isPresent())
|
||||
if (!ability_opt.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure it was a triggered ability (needed for checking if it's a chapter
|
||||
// ability)
|
||||
Ability ability = ability_opt.get();
|
||||
if (!(ability instanceof TriggeredAbility))
|
||||
if (!(ability.isTriggeredAbility())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure it was a chapter ability
|
||||
TriggeredAbility triggeredAbility = (TriggeredAbility) ability;
|
||||
if (!SagaAbility.isChapterAbility(triggeredAbility))
|
||||
if (!SagaAbility.isChapterAbility(triggeredAbility)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// There's a chance that the permanent that this abiltiy came from no longer
|
||||
// exists, so try and find it on the battlefield or check last known
|
||||
|
|
@ -75,17 +78,17 @@ public class FinalChapterAbilityResolvesTriggeredAbility extends TriggeredAbilit
|
|||
// chapter ability on that permanent.
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||
if (permanent == null
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|| !permanent.hasSubtype(SubType.SAGA, game)) {
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|| !permanent.hasSubtype(SubType.SAGA, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the max chapter number from that permanent
|
||||
int maxChapter = CardUtil
|
||||
.castStream(permanent.getAbilities(game).stream(), SagaAbility.class)
|
||||
.map(SagaAbility::getMaxChapter)
|
||||
.mapToInt(SagaChapter::getNumber)
|
||||
.sum();
|
||||
.castStream(permanent.getAbilities(game).stream(), SagaAbility.class)
|
||||
.map(SagaAbility::getMaxChapter)
|
||||
.mapToInt(SagaChapter::getNumber)
|
||||
.sum();
|
||||
|
||||
// Check if the ability was the last one
|
||||
if (!SagaAbility.isFinalAbility(triggeredAbility, maxChapter)) {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public class SacrificeAllCost extends CostImpl implements SacrificeCost {
|
|||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
UUID activator = controllerId;
|
||||
if (ability.getAbilityType() == AbilityType.ACTIVATED || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.getAbilityType().isActivatedAbility() || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (((ActivatedAbilityImpl) ability).getActivatorId() != null) {
|
||||
activator = ((ActivatedAbilityImpl) ability).getActivatorId();
|
||||
} // else, Activator not filled?
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public class SacrificeTargetCost extends CostImpl implements SacrificeCost {
|
|||
|
||||
/**
|
||||
* Sacrifice a permanent matching the filter:
|
||||
*
|
||||
* @param filter can be generic, will automatically add article and sacrifice predicates
|
||||
*/
|
||||
public SacrificeTargetCost(FilterPermanent filter) {
|
||||
|
|
@ -35,6 +36,7 @@ public class SacrificeTargetCost extends CostImpl implements SacrificeCost {
|
|||
|
||||
/**
|
||||
* Sacrifice N permanents matching the filter:
|
||||
*
|
||||
* @param filter can be generic, will automatically add sacrifice predicates
|
||||
*/
|
||||
public SacrificeTargetCost(int numToSac, FilterPermanent filter) {
|
||||
|
|
@ -57,7 +59,7 @@ public class SacrificeTargetCost extends CostImpl implements SacrificeCost {
|
|||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
UUID activator = controllerId;
|
||||
if (ability.getAbilityType() == AbilityType.ACTIVATED || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.getAbilityType().isActivatedAbility() || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
activator = ((ActivatedAbilityImpl) ability).getActivatorId();
|
||||
}
|
||||
// can be cancel by user
|
||||
|
|
@ -87,7 +89,7 @@ public class SacrificeTargetCost extends CostImpl implements SacrificeCost {
|
|||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
UUID activator = controllerId;
|
||||
if (ability.getAbilityType() == AbilityType.ACTIVATED || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (ability.getAbilityType().isActivatedAbility() || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
if (((ActivatedAbilityImpl) ability).getActivatorId() != null) {
|
||||
activator = ((ActivatedAbilityImpl) ability).getActivatorId();
|
||||
} // else, Activator not filled?
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -42,7 +41,7 @@ public class GainActivatedAbilitiesOfTopCardEffect extends ContinuousEffectImpl
|
|||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
for (Ability ability : card.getAbilities(game)) {
|
||||
if (ability instanceof ActivatedAbility) {
|
||||
if (ability.isActivatedAbility()) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
|
|
@ -106,7 +105,7 @@ public class GainControlTargetEffect extends ContinuousEffectImpl {
|
|||
controlChanged = true;
|
||||
}
|
||||
}
|
||||
if (source instanceof ActivatedAbility
|
||||
if (source.isActivatedAbility()
|
||||
&& firstControlChange && !controlChanged) {
|
||||
// If it was not possible to get control of target permanent by the activated ability the first time it took place
|
||||
// the effect failed (e.g. because of Guardian Beast) and must be discarded
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package mage.abilities.effects.common.ruleModifying;
|
|||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -86,7 +85,7 @@ public class TargetsHaveToTargetPermanentIfAbleEffect extends ContinuousRuleModi
|
|||
}
|
||||
Ability stackAbility = stackObject.getStackAbility();
|
||||
// Ensure that this ability is activated or a cast spell, because Flag Bearer effects don't require triggered abilities to choose a Standard Bearer
|
||||
if (!(stackAbility instanceof ActivatedAbility) &&
|
||||
if (!(stackAbility.isActivatedAbility()) &&
|
||||
!(stackAbility instanceof SpellAbility)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ package mage.abilities.effects.mana;
|
|||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
|
|
@ -39,7 +37,7 @@ public abstract class ManaEffect extends OneShotEffect {
|
|||
// During calculation of the available mana for a player the "TappedForMana" event is fired to simulate triggered mana production.
|
||||
// By checking the inCheckPlayableState these events are handled to give back only the available mana of instead really producing mana
|
||||
// So it's important if ManaEffects overwrite the apply method to take care for this.
|
||||
if (source instanceof TriggeredAbility) {
|
||||
if (source.isTriggeredAbility()) {
|
||||
player.addAvailableTriggeredMana(getNetMana(game, source));
|
||||
}
|
||||
return true; // No need to add mana to pool during checkPlayable
|
||||
|
|
@ -132,7 +130,7 @@ public abstract class ManaEffect extends OneShotEffect {
|
|||
* @param source
|
||||
*/
|
||||
public void checkToFirePossibleEvents(Mana mana, Game game, Ability source) {
|
||||
if (source.getAbilityType() == AbilityType.MANA && source.hasTapCost()) {
|
||||
if (source.getAbilityType().isManaAbility() && source.hasTapCost()) {
|
||||
ManaEvent event = new TappedForManaEvent(source.getSourceId(), source, source.getControllerId(), mana, game);
|
||||
if (!game.replaceEvent(event)) {
|
||||
game.fireEvent(event);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package mage.abilities.keyword;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -14,11 +13,11 @@ import java.util.Optional;
|
|||
|
||||
/**
|
||||
* Split Second
|
||||
*
|
||||
* <p>
|
||||
* As long as this spell is on the stack, players can't cast other spells or activate abilities that aren't mana abilities.
|
||||
*/
|
||||
|
||||
public class SplitSecondAbility extends SimpleStaticAbility {
|
||||
public class SplitSecondAbility extends SimpleStaticAbility {
|
||||
|
||||
public SplitSecondAbility() {
|
||||
super(Zone.STACK, new SplitSecondEffect());
|
||||
|
|
@ -70,7 +69,7 @@ class SplitSecondEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
}
|
||||
if (event.getType() == GameEvent.EventType.ACTIVATE_ABILITY) {
|
||||
Optional<Ability> ability = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (ability.isPresent() && !(ability.get() instanceof ActivatedManaAbilityImpl)) {
|
||||
if (ability.isPresent() && !ability.get().isManaActivatedAbility()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
|||
protected boolean poolDependant;
|
||||
|
||||
public ActivatedManaAbilityImpl(Zone zone, ManaEffect effect, Cost cost) {
|
||||
super(AbilityType.MANA, zone);
|
||||
super(AbilityType.ACTIVATED_MANA, zone);
|
||||
this.usesStack = false;
|
||||
this.undoPossible = true;
|
||||
if (effect != null) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.abilities.TriggeredAbilityImpl;
|
|||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
|
|
@ -13,8 +14,6 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import mage.constants.ManaType;
|
||||
|
||||
/**
|
||||
* see 20110715 - 605.1b
|
||||
*
|
||||
|
|
@ -32,8 +31,7 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen
|
|||
public TriggeredManaAbility(Zone zone, ManaEffect effect, boolean optional) {
|
||||
super(zone, effect, optional);
|
||||
this.usesStack = false;
|
||||
this.abilityType = AbilityType.MANA;
|
||||
|
||||
this.abilityType = AbilityType.TRIGGERED_MANA;
|
||||
}
|
||||
|
||||
protected TriggeredManaAbility(final TriggeredManaAbility ability) {
|
||||
|
|
|
|||
|
|
@ -1,26 +1,32 @@
|
|||
package mage.constants;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
* @author North, Susucr
|
||||
*/
|
||||
public enum AbilityType {
|
||||
PLAY_LAND("Play land", true),
|
||||
MANA("Mana", false),
|
||||
SPELL("Spell", true),
|
||||
ACTIVATED("Activated", false),
|
||||
STATIC("Static", false),
|
||||
TRIGGERED("Triggered", false),
|
||||
EVASION("Evasion", false),
|
||||
LOYALTY("Loyalty", false),
|
||||
SPECIAL_ACTION("Special Action", false),
|
||||
SPECIAL_MANA_PAYMENT("Special Mana Payment", false); // No activated ability and no special action. (e.g. Improvise, Delve)
|
||||
PLAY_LAND("Play land", true, false, false, false),
|
||||
SPELL("Spell", true, false, false, false),
|
||||
STATIC("Static", false, false, false, false),
|
||||
EVASION("Evasion", false, false, false, false),
|
||||
ACTIVATED_NONMANA("Activated", false, true, false, false),
|
||||
ACTIVATED_MANA("Mana", false, true, false, true),
|
||||
TRIGGERED_NONMANA("Triggered", false, false, true, false),
|
||||
TRIGGERED_MANA("Triggered Mana", false, false, true, true),
|
||||
SPECIAL_ACTION("Special Action", false, false, false, false),
|
||||
SPECIAL_MANA_PAYMENT("Special Mana Payment", false, false, false, false); // No activated ability and no special action. (e.g. Improvise, Delve)
|
||||
|
||||
private final String text;
|
||||
private final boolean playCardAbility;
|
||||
private final boolean activatedAbility;
|
||||
private final boolean triggeredAbility;
|
||||
private final boolean manaAbility;
|
||||
|
||||
AbilityType(String text, boolean playCardAbility) {
|
||||
AbilityType(String text, boolean playCardAbility, boolean activatedAbility, boolean triggeredAbility, boolean manaAbility) {
|
||||
this.text = text;
|
||||
this.playCardAbility = playCardAbility;
|
||||
this.activatedAbility = activatedAbility;
|
||||
this.triggeredAbility = triggeredAbility;
|
||||
this.manaAbility = manaAbility;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -31,4 +37,24 @@ public enum AbilityType {
|
|||
public boolean isPlayCardAbility() {
|
||||
return playCardAbility;
|
||||
}
|
||||
|
||||
public boolean isActivatedAbility() {
|
||||
return activatedAbility;
|
||||
}
|
||||
|
||||
public boolean isTriggeredAbility() {
|
||||
return triggeredAbility;
|
||||
}
|
||||
|
||||
public boolean isNonManaActivatedAbility() {
|
||||
return activatedAbility && !manaAbility;
|
||||
}
|
||||
|
||||
public boolean isManaActivatedAbility() {
|
||||
return activatedAbility && manaAbility;
|
||||
}
|
||||
|
||||
public boolean isManaAbility() {
|
||||
return manaAbility;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
package mage.filter.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.filter.FilterStackObject;
|
||||
import mage.filter.predicate.other.ActivatedOrTriggeredAbilityPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.filter.predicate.other.ActivatedOrTriggeredAbilityPredicate;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
|
|
@ -29,25 +28,23 @@ public class FilterActivatedOrTriggeredAbility extends FilterStackObject {
|
|||
|
||||
@Override
|
||||
public boolean match(StackObject stackObject, UUID playerId, Ability source, Game game) {
|
||||
|
||||
|
||||
if (!super.match(stackObject, playerId, source, game)
|
||||
|| !(stackObject instanceof Ability)) {
|
||||
return false;
|
||||
}
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
return ability.isTriggeredAbility() || ability.isActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(StackObject stackObject, Game game) {
|
||||
|
||||
|
||||
if (!super.match(stackObject, game)
|
||||
|| !(stackObject instanceof Ability)) {
|
||||
return false;
|
||||
}
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
return ability.getAbilityType().isTriggeredAbility() || ability.isActivatedAbility();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
package mage.filter.predicate.other;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public enum ActivatedOrTriggeredAbilityPredicate implements Predicate<StackObject> {
|
||||
|
|
@ -19,8 +17,7 @@ public enum ActivatedOrTriggeredAbilityPredicate implements Predicate<StackObjec
|
|||
return false;
|
||||
}
|
||||
Ability ability = ((Ability) input);
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED;
|
||||
return ability.isTriggeredAbility() || ability.isActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package mage.game.command.emblems;
|
|||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.CopyStackObjectEffect;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.Emblem;
|
||||
|
|
@ -56,7 +55,7 @@ class RowanKenrithEmblemTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return false;
|
||||
}
|
||||
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
|
||||
if (stackAbility == null || stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl) {
|
||||
if (stackAbility == null || stackAbility.getStackAbility().isManaActivatedAbility()) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setValue("stackObject", stackAbility);
|
||||
|
|
|
|||
|
|
@ -430,6 +430,31 @@ public class StackAbility extends StackObjectImpl implements Ability {
|
|||
return ability.getAbilityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActivatedAbility() {
|
||||
return ability.isActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTriggeredAbility() {
|
||||
return ability.isTriggeredAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNonManaActivatedAbility() {
|
||||
return ability.isNonManaActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManaActivatedAbility() {
|
||||
return ability.isManaActivatedAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManaAbility() {
|
||||
return ability.isManaAbility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsesStack() {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1592,7 +1592,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
case SPECIAL_MANA_PAYMENT:
|
||||
result = specialManaPayment((SpecialAction) ability.copy(), game);
|
||||
break;
|
||||
case MANA:
|
||||
case ACTIVATED_MANA:
|
||||
result = playManaAbility((ActivatedManaAbilityImpl) ability.copy(), game);
|
||||
break;
|
||||
case SPELL:
|
||||
|
|
@ -1616,9 +1616,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
//if player has taken an action then reset all player passed flags
|
||||
justActivatedType = null;
|
||||
if (result) {
|
||||
if (isHuman()
|
||||
&& (ability.getAbilityType() == AbilityType.SPELL
|
||||
|| ability.getAbilityType() == AbilityType.ACTIVATED)) {
|
||||
if (isHuman() && (ability.getAbilityType() == AbilityType.SPELL || ability.getAbilityType().isActivatedAbility())) {
|
||||
if (ability.isUsesStack()) { // if the ability does not use the stack (e.g. Suspend) auto pass would go to next phase unintended
|
||||
setJustActivatedType(ability.getAbilityType());
|
||||
}
|
||||
|
|
@ -2400,7 +2398,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
||||
|
||||
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, false);
|
||||
if (game.replaceEvent(removeCountersEvent)){
|
||||
if (game.replaceEvent(removeCountersEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2408,7 +2406,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
for (int i = 0; i < amount; i++) {
|
||||
|
||||
GameEvent event = new RemoveCounterEvent(name, this, source, false);
|
||||
if (game.replaceEvent(event)){
|
||||
if (game.replaceEvent(event)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -3582,7 +3580,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
* @return
|
||||
*/
|
||||
protected boolean canPlay(ActivatedAbility ability, ManaOptions availableMana, MageObject sourceObject, Game game) {
|
||||
if (!(ability instanceof ActivatedManaAbilityImpl)) {
|
||||
if (!ability.isManaActivatedAbility()) {
|
||||
ActivatedAbility copy = ability.copy(); // Copy is needed because cost reduction effects modify e.g. the mana to activate/cast the ability
|
||||
if (!copy.canActivate(playerId, game).canActivate()) {
|
||||
return false;
|
||||
|
|
@ -3885,7 +3883,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
// alternative cost must be replaced by real play ability
|
||||
return findActivatedAbilityFromAlternativeSourceCost(object, manaFull, ability, game);
|
||||
} else if (ability instanceof ActivatedAbility) {
|
||||
// all other activated ability
|
||||
// all other abilities (include PlayLandAbility & SpellAbility)
|
||||
if (canPlay((ActivatedAbility) ability, manaFull, object, game)) {
|
||||
return (ActivatedAbility) ability;
|
||||
}
|
||||
|
|
@ -3964,6 +3962,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
// check "can play" condition as affected controller (BUT play from not own hand zone must be checked as original controller)
|
||||
// must check all abilities, not activated only
|
||||
for (Ability ability : candidateAbilities) {
|
||||
// Note: SpellAbility and PlayLandAbility are ActivatedAbility
|
||||
if (!(ability instanceof ActivatedAbility)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -4493,9 +4492,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
case allAbilities:
|
||||
return true;
|
||||
case onlyManaAbilities:
|
||||
return ability.getAbilityType() == AbilityType.MANA;
|
||||
return ability.isManaAbility();
|
||||
case nonSpellnonActivatedAbilities:
|
||||
return ability.getAbilityType() != AbilityType.ACTIVATED && ability.getAbilityType() != AbilityType.SPELL;
|
||||
return !ability.getAbilityType().isActivatedAbility()
|
||||
&& ability.getAbilityType() != AbilityType.SPELL;
|
||||
case none:
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -203,7 +203,9 @@ public abstract class TargetImpl implements Target {
|
|||
|
||||
@Override
|
||||
public boolean isRequired(Ability ability) {
|
||||
return ability == null || ability.isActivated() || !(ability.getAbilityType() == AbilityType.SPELL || ability.getAbilityType() == AbilityType.ACTIVATED);
|
||||
return ability == null
|
||||
|| ability.isActivated()
|
||||
|| !(ability.getAbilityType() == AbilityType.SPELL || ability.getAbilityType().isActivatedAbility());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -675,10 +677,10 @@ public abstract class TargetImpl implements Target {
|
|||
String abilityText = source.getRule(true).toLowerCase();
|
||||
boolean strictModeEnabled = player.getStrictChooseMode();
|
||||
boolean canAutoChoose = this.getMinNumberOfTargets() == this.getMaxNumberOfTargets() // Targets must be picked
|
||||
&& possibleTargets.size() == this.getNumberOfTargets() - this.getSize() // Available targets are equal to the number that must be picked
|
||||
&& !strictModeEnabled // Test AI is not set to strictChooseMode(true)
|
||||
&& playerAutoTargetLevel > 0 // Human player has enabled auto-choose in settings
|
||||
&& !abilityText.contains("search"); // Do not autochoose for any effects which involve searching
|
||||
&& possibleTargets.size() == this.getNumberOfTargets() - this.getSize() // Available targets are equal to the number that must be picked
|
||||
&& !strictModeEnabled // Test AI is not set to strictChooseMode(true)
|
||||
&& playerAutoTargetLevel > 0 // Human player has enabled auto-choose in settings
|
||||
&& !abilityText.contains("search"); // Do not autochoose for any effects which involve searching
|
||||
|
||||
|
||||
if (canAutoChoose) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package mage.target.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterAbility;
|
||||
|
|
@ -48,7 +47,7 @@ public class TargetActivatedAbility extends TargetObject {
|
|||
StackObject stackObject = game.getStack().getStackObject(id);
|
||||
return stackObject != null
|
||||
&& stackObject.getStackAbility() != null
|
||||
&& stackObject.getStackAbility().getAbilityType() == AbilityType.ACTIVATED
|
||||
&& stackObject.getStackAbility().isActivatedAbility()
|
||||
&& source != null
|
||||
&& filter.match(stackObject, source.getControllerId(), source, game);
|
||||
}
|
||||
|
|
@ -62,8 +61,9 @@ public class TargetActivatedAbility extends TargetObject {
|
|||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject.getStackAbility() != null
|
||||
&& stackObject.getStackAbility().getAbilityType() == AbilityType.ACTIVATED
|
||||
&& game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getStackAbility().getControllerId())) {
|
||||
&& stackObject.getStackAbility().isActivatedAbility()
|
||||
&& game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getStackAbility().getControllerId())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ public class TargetActivatedAbility extends TargetObject {
|
|||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
||||
Set<UUID> possibleTargets = new HashSet<>();
|
||||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject.getStackAbility().getAbilityType() == AbilityType.ACTIVATED
|
||||
if (stackObject.getStackAbility().isActivatedAbility()
|
||||
&& game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getStackAbility().getControllerId())
|
||||
&& filter.match(stackObject, game)) {
|
||||
possibleTargets.add(stackObject.getStackAbility().getId());
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package mage.target.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterStackObject;
|
||||
|
|
@ -93,7 +92,7 @@ public class TargetTriggeredAbility extends TargetObject {
|
|||
}
|
||||
if (stackObject instanceof Ability) {
|
||||
Ability ability = (Ability) stackObject;
|
||||
return ability.getAbilityType() == AbilityType.TRIGGERED;
|
||||
return ability.getAbilityType().isTriggeredAbility();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue