mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
Adeded ContinuousRuleModifyingEffect and handling for it. This effects will also be taken into account when checking if a spell gets yellow frame if it can be cast.
This commit is contained in:
parent
4604b076eb
commit
05a2e09b2a
5 changed files with 195 additions and 5 deletions
|
@ -39,6 +39,7 @@ import mage.constants.SpellAbilityType;
|
|||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -97,6 +98,14 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
if (this.getManaCosts().isEmpty() && this.getCosts().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
// Check if rule modifying events prevent to cast the spell in check playable mode
|
||||
if (this.isCheckPlayableMode()) {
|
||||
if (game.getContinuousEffects().preventedByRuleModification(
|
||||
GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, this.getId(), this.getSourceId(), playerId), game, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (costs.canPay(sourceId, controllerId, game)) {
|
||||
if (getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) {
|
||||
SplitCard splitCard = (SplitCard) game.getCard(getSourceId());
|
||||
|
|
|
@ -80,6 +80,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
//transient Continuous effects
|
||||
private ContinuousEffectsList<ContinuousEffect> layeredEffects = new ContinuousEffectsList<>();
|
||||
private ContinuousEffectsList<ContinuousRuleModifiyingEffect> continuousRuleModifyingEffects = new ContinuousEffectsList<>();
|
||||
private ContinuousEffectsList<ReplacementEffect> replacementEffects = new ContinuousEffectsList<>();
|
||||
private ContinuousEffectsList<PreventionEffect> preventionEffects = new ContinuousEffectsList<>();
|
||||
private ContinuousEffectsList<RequirementEffect> requirementEffects = new ContinuousEffectsList<>();
|
||||
|
@ -111,6 +112,7 @@ public class ContinuousEffects implements Serializable {
|
|||
this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy();
|
||||
this.auraReplacementEffect = effect.auraReplacementEffect.copy();
|
||||
layeredEffects = effect.layeredEffects.copy();
|
||||
continuousRuleModifyingEffects = effect.continuousRuleModifyingEffects.copy();
|
||||
replacementEffects = effect.replacementEffects.copy();
|
||||
preventionEffects = effect.preventionEffects.copy();
|
||||
requirementEffects = effect.requirementEffects.copy();
|
||||
|
@ -130,7 +132,8 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
|
||||
private void collectAllEffects() {
|
||||
allEffectsLists.add(layeredEffects);
|
||||
allEffectsLists.add(layeredEffects);
|
||||
allEffectsLists.add(continuousRuleModifyingEffects);
|
||||
allEffectsLists.add(replacementEffects);
|
||||
allEffectsLists.add(preventionEffects);
|
||||
allEffectsLists.add(requirementEffects);
|
||||
|
@ -157,6 +160,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
public void removeEndOfCombatEffects() {
|
||||
layeredEffects.removeEndOfCombatEffects();
|
||||
continuousRuleModifyingEffects.removeEndOfCombatEffects();
|
||||
replacementEffects.removeEndOfCombatEffects();
|
||||
preventionEffects.removeEndOfCombatEffects();
|
||||
requirementEffects.removeEndOfCombatEffects();
|
||||
|
@ -170,6 +174,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
public void removeEndOfTurnEffects() {
|
||||
layeredEffects.removeEndOfTurnEffects();
|
||||
continuousRuleModifyingEffects.removeEndOfTurnEffects();
|
||||
replacementEffects.removeEndOfTurnEffects();
|
||||
preventionEffects.removeEndOfTurnEffects();
|
||||
requirementEffects.removeEndOfTurnEffects();
|
||||
|
@ -183,6 +188,7 @@ public class ContinuousEffects implements Serializable {
|
|||
|
||||
public void removeInactiveEffects(Game game) {
|
||||
layeredEffects.removeInactiveEffects(game);
|
||||
continuousRuleModifyingEffects.removeInactiveEffects(game);
|
||||
replacementEffects.removeInactiveEffects(game);
|
||||
preventionEffects.removeInactiveEffects(game);
|
||||
requirementEffects.removeInactiveEffects(game);
|
||||
|
@ -320,8 +326,7 @@ public class ContinuousEffects implements Serializable {
|
|||
* @param game
|
||||
* @return a list of all {@link ReplacementEffect} that apply to the current event
|
||||
*/
|
||||
private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
|
||||
// List<ReplacementEffect> replaceEffects = new ArrayList<ReplacementEffect>();
|
||||
private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
|
||||
HashMap<ReplacementEffect, HashSet<Ability>> replaceEffects = new HashMap<>();
|
||||
if (planeswalkerRedirectionEffect.applies(event, null, game)) {
|
||||
replaceEffects.put(planeswalkerRedirectionEffect, null);
|
||||
|
@ -588,8 +593,34 @@ public class ContinuousEffects implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean preventedByRuleModification(GameEvent event, Game game, boolean checkPlayableMode) {
|
||||
for (ContinuousRuleModifiyingEffect effect: continuousRuleModifyingEffects) {
|
||||
for (Ability ability : continuousRuleModifyingEffects.getAbility(effect.getId())) {
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false)) {
|
||||
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
|
||||
if (effect.applies(event, ability, checkPlayableMode, game)) {
|
||||
if (!checkPlayableMode) {
|
||||
String message = effect.getInfoMessage(ability, game);
|
||||
if (message != null && !message.isEmpty()) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if (player != null) {
|
||||
game.informPlayer(player, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean replaceEvent(GameEvent event, Game game) {
|
||||
if (preventedByRuleModification(event, game, false)) {
|
||||
return true;
|
||||
}
|
||||
boolean caught = false;
|
||||
HashMap<UUID, HashSet<UUID>> consumed = new HashMap<>();
|
||||
do {
|
||||
|
@ -860,6 +891,10 @@ public class ContinuousEffects implements Serializable {
|
|||
SpliceCardEffect newSpliceCardEffect = (SpliceCardEffect)effect;
|
||||
spliceCardEffects.addEffect(newSpliceCardEffect, source);
|
||||
break;
|
||||
case CONTINUOUS_RULE_MODIFICATION:
|
||||
ContinuousRuleModifiyingEffect newContinuousRuleModifiyingEffect = (ContinuousRuleModifiyingEffect)effect;
|
||||
continuousRuleModifyingEffects.addEffect(newContinuousRuleModifiyingEffect, source);
|
||||
break;
|
||||
default:
|
||||
layeredEffects.addEffect(effect, source);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.abilities.effects;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public interface ContinuousRuleModifiyingEffect extends ContinuousEffect {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param event the event to check if it may happen
|
||||
* @param source the ability of the effect
|
||||
* @param checkPlayableMode is the call for checking playables or to prevent a real event
|
||||
* @param game the game
|
||||
* @return
|
||||
*/
|
||||
boolean applies(GameEvent event, Ability source, boolean checkPlayableMode, Game game);
|
||||
|
||||
/**
|
||||
* Returns a message text that informs the player why he can't do something.
|
||||
*
|
||||
* @param source the ability of the effect
|
||||
* @param game the game
|
||||
* @return
|
||||
*/
|
||||
String getInfoMessage(Ability source, Game game);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.abilities.effects;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.EffectType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public abstract class ContinuousRuleModifiyingEffectImpl extends ContinuousEffectImpl implements ContinuousRuleModifiyingEffect {
|
||||
|
||||
protected final String infoMessage;
|
||||
|
||||
// 613.10
|
||||
// Some continuous effects affect game rules rather than objects. For example, effects may modify
|
||||
// a players maximum hand size, or say that a creature must attack this turn if able. These effects
|
||||
// are applied after all other continuous effects have been applied. Continuous effects that affect
|
||||
// the costs of spells or abilities are applied according to the order specified in rule 601.2e.
|
||||
// All other such effects are applied in timestamp order. See also the rules for timestamp order
|
||||
// and dependency (rules 613.6 and 613.7).
|
||||
|
||||
// Some of this rule modifying effects are implemented as normal CONTINUOUS effects using the Layer.RulesEffects.
|
||||
// But if the rule change can be implemented simply by preventing an event from happening, CONTINUOUS_RULE_MODIFICATION effects can be used.
|
||||
// They work technical like a replacement effect that replaces the event completely.
|
||||
// But player isn't asked to choose order of effects if multiple are applied to the same event.
|
||||
|
||||
public ContinuousRuleModifiyingEffectImpl(Duration duration, Outcome outcome) {
|
||||
super(duration, outcome);
|
||||
this.effectType = EffectType.CONTINUOUS_RULE_MODIFICATION;
|
||||
this.infoMessage = null;
|
||||
}
|
||||
|
||||
public ContinuousRuleModifiyingEffectImpl(final ContinuousRuleModifiyingEffectImpl effect) {
|
||||
super(effect);
|
||||
this.infoMessage = effect.infoMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfoMessage(Ability source, Game game) {
|
||||
if (infoMessage == null) {
|
||||
String message = null;
|
||||
MageObject object = game.getObject(source.getSourceId());
|
||||
if (object != null) {
|
||||
message = source.getRule(object.getLogName());
|
||||
} else {
|
||||
message = source.getRule();
|
||||
}
|
||||
return message;
|
||||
} else {
|
||||
return infoMessage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ public enum EffectType {
|
|||
|
||||
ONESHOT("One Shot Effect"),
|
||||
CONTINUOUS("Continuous Effect"),
|
||||
CONTINUOUS_RULE_MODIFICATION("Layered rule modification"),
|
||||
REPLACEMENT("Replacement Effect"),
|
||||
PREVENTION("Prevention Effect"),
|
||||
REDIRECTION("Redirection Effect"),
|
||||
|
@ -18,7 +19,7 @@ public enum EffectType {
|
|||
COSTMODIFICATION("Cost Modification Effect"),
|
||||
SPLICE("Splice Card Effect");
|
||||
|
||||
private String text;
|
||||
private final String text;
|
||||
|
||||
EffectType(String text) {
|
||||
this.text = text;
|
||||
|
|
Loading…
Reference in a new issue