From 31fedb27a6a751a9d9aa0e56254fb401dc8c2a96 Mon Sep 17 00:00:00 2001 From: "maurer.it" Date: Mon, 17 Jan 2011 23:03:40 -0500 Subject: [PATCH] Much better than revision 4e7269ad70 --- .../src/mage/sets/worldwake/EyeofUgin.java | 49 ++++++-------- Mage/src/mage/Constants.java | 3 +- Mage/src/mage/abilities/AbilityImpl.java | 19 +++++- .../abilities/effects/ContinuousEffects.java | 45 +++++++++++++ .../effects/CostModificationEffect.java | 67 +++++++++++++++++++ .../effects/CostModificationEffectImpl.java | 66 ++++++++++++++++++ 6 files changed, 220 insertions(+), 29 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/CostModificationEffect.java create mode 100644 Mage/src/mage/abilities/effects/CostModificationEffectImpl.java diff --git a/Mage.Sets/src/mage/sets/worldwake/EyeofUgin.java b/Mage.Sets/src/mage/sets/worldwake/EyeofUgin.java index cc1fa8512d..ac99118531 100644 --- a/Mage.Sets/src/mage/sets/worldwake/EyeofUgin.java +++ b/Mage.Sets/src/mage/sets/worldwake/EyeofUgin.java @@ -31,10 +31,8 @@ package mage.sets.worldwake; import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Duration; -import mage.Constants.Layer; import mage.Constants.Outcome; import mage.Constants.Rarity; -import mage.Constants.SubLayer; import mage.Constants.Zone; import mage.abilities.Ability; import mage.abilities.SpellAbility; @@ -42,14 +40,12 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.CostModificationEffectImpl; import mage.abilities.effects.common.SearchLibraryRevealPutInHandEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.filter.common.FilterCreatureCard; import mage.game.Game; -import mage.game.stack.Spell; -import mage.game.stack.SpellStack; -import mage.game.stack.StackObject; import mage.target.common.TargetCardInLibrary; /** @@ -89,12 +85,12 @@ public class EyeofUgin extends CardImpl { } } -class EyeofUginCostReductionEffect extends ContinuousEffectImpl { +class EyeofUginCostReductionEffect extends CostModificationEffectImpl { private static final String effectText = "Colorless Eldrazi spells you cast cost {2} less to cast"; EyeofUginCostReductionEffect ( ) { - super(Duration.WhileOnBattlefield, Layer.TextChangingEffects_3, SubLayer.NA, Outcome.Benefit); + super(Duration.WhileOnBattlefield, Outcome.Benefit); } EyeofUginCostReductionEffect(EyeofUginCostReductionEffect effect) { @@ -102,28 +98,27 @@ class EyeofUginCostReductionEffect extends ContinuousEffectImpl 0 ) { + adjustedCost = previousCost - 2; + } + spellAbility.getManaCostsToPay().load("{" + adjustedCost + "}"); - for ( int idx = 0; idx < stack.size(); idx++ ) { - StackObject stackObject = stack.get(idx); - - if ( stackObject instanceof Spell && - ((Spell)stackObject).getSubtype().contains("Eldrazi")) - { - SpellAbility spell = ((Spell)stackObject).getSpellAbility(); - int previousCost = spell.getManaCosts().convertedManaCost(); - int adjustedCost = 0; - if ( (previousCost - 2) > 0 ) { - adjustedCost = previousCost - 2; - } - spell.getManaCosts().load("{" + adjustedCost + "}"); - applied = true; + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + if ( abilityToModify instanceof SpellAbility ) { + Card sourceCard = game.getCard(((SpellAbility)abilityToModify).getSourceId()); + if ( sourceCard != null && sourceCard.getSubtype().contains("Eldrazi") && sourceCard.getOwnerId().equals(source.getControllerId()) ) { + return true; } } - - return applied; + return false; } @Override diff --git a/Mage/src/mage/Constants.java b/Mage/src/mage/Constants.java index 927c569bee..9db2b245eb 100644 --- a/Mage/src/mage/Constants.java +++ b/Mage/src/mage/Constants.java @@ -153,7 +153,8 @@ public final class Constants { REDIRECTION("Redirection Effect"), ASTHOUGH("As Though Effect"), RESTRICTION("Restriction Effect"), - REQUIREMENT("Requirement Effect"); + REQUIREMENT("Requirement Effect"), + COSTMODIFICATION("Cost Modification Effect"); private String text; diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index fdfe229c7a..8656bd09f2 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -68,6 +68,7 @@ public abstract class AbilityImpl> implements Ability { protected UUID controllerId; protected UUID sourceId; protected ManaCosts manaCosts; + protected ManaCosts manaCostsToPay; protected Costs costs; protected ArrayList alternativeCosts = new ArrayList(); protected Costs optionalCosts; @@ -87,6 +88,7 @@ public abstract class AbilityImpl> implements Ability { this.abilityType = abilityType; this.zone = zone; this.manaCosts = new ManaCostsImpl(); + this.manaCostsToPay = new ManaCostsImpl(); this.costs = new CostsImpl(); this.optionalCosts = new CostsImpl(); this.effects = new Effects(); @@ -104,6 +106,7 @@ public abstract class AbilityImpl> implements Ability { this.name = ability.name; this.usesStack = ability.usesStack; this.manaCosts = ability.manaCosts.copy(); + this.manaCostsToPay = ability.manaCostsToPay.copy(); this.costs = ability.costs.copy(); this.optionalCosts = ability.optionalCosts.copy(); for (AlternativeCost cost: ability.alternativeCosts) { @@ -162,8 +165,11 @@ public abstract class AbilityImpl> implements Ability { if (game.getObject(sourceId) != null) game.getObject(sourceId).adjustCosts(this, game); if (!useAlternativeCost(game)) { + //20101001 - 601.2e + game.getContinuousEffects().costModification(this, game); + //20100716 - 601.2f - if (!manaCosts.pay(game, sourceId, controllerId, noMana)) { + if (!manaCostsToPay.pay(game, sourceId, controllerId, noMana)) { logger.fine("activate failed - mana"); return false; } @@ -225,6 +231,16 @@ public abstract class AbilityImpl> implements Ability { return manaCosts; } + /** + * Should be used by {@link mage.abilities.effects.CostModificationEffect cost modification effects} + * to manipulate what is actually paid before resolution. + * + * @return + */ + public ManaCosts getManaCostsToPay ( ) { + return manaCostsToPay; + } + @Override public List getAlternativeCosts() { return alternativeCosts; @@ -324,6 +340,7 @@ public abstract class AbilityImpl> implements Ability { public void addManaCost(ManaCost cost) { if (cost != null) { this.manaCosts.add(cost); + this.manaCostsToPay.add(cost); } } diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index 08f44cbc2f..bb6713ea9e 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -65,6 +65,7 @@ public class ContinuousEffects implements Serializable { private final List requirementEffects = new ArrayList(); private final List restrictionEffects = new ArrayList(); private final List asThoughEffects = new ArrayList(); + private final List costModificationEffects = new ArrayList(); //map Abilities to Continuous effects private final Map abilityMap = new HashMap(); @@ -98,6 +99,9 @@ public class ContinuousEffects implements Serializable { for (AsThoughEffect entry: effect.asThoughEffects) { asThoughEffects.add((AsThoughEffect)entry.copy()); } + for ( CostModificationEffect entry : effect.costModificationEffects ) { + costModificationEffects.add(entry); + } for (Entry entry: effect.abilityMap.entrySet()) { abilityMap.put(entry.getKey(), entry.getValue().copy()); } @@ -150,6 +154,11 @@ public class ContinuousEffects implements Serializable { if (entry.getDuration() == Duration.EndOfTurn) i.remove(); } + for (Iterator i = costModificationEffects.iterator(); i.hasNext();) { + ContinuousEffect entry = i.next(); + if (entry.getDuration() == Duration.EndOfTurn) + i.remove(); + } } public void removeInactiveEffects(Game game) { @@ -177,6 +186,10 @@ public class ContinuousEffects implements Serializable { if (isInactive(i.next(), game)) i.remove(); } + for (Iterator i = costModificationEffects.iterator(); i.hasNext();) { + if (isInactive(i.next(), game)) + i.remove(); + } } private boolean isInactive(ContinuousEffect effect, Game game) { @@ -357,6 +370,33 @@ public class ContinuousEffects implements Serializable { return false; } + /** + * Inspects all {@link Permanent permanent's} {@link Ability abilities} on the battlefied + * for {@link CostModificationEffect cost modification effects} and applies them if necessary. + * + * @param objectId + * @param abilityToModify + * @param game + * @return + */ + public void costModification ( Ability abilityToModify, Game game ) { + for ( Permanent permanent : game.getBattlefield().getAllPermanents() ) { + for ( Ability ability : permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD) ) { + for ( Effect effect : ability.getEffects(EffectType.COSTMODIFICATION) ) { + CostModificationEffect rEffect = (CostModificationEffect)effect; + if ( rEffect.applies(abilityToModify, ability, game) ) { + rEffect.apply(game, ability, abilityToModify); + } + } + } + } + for ( CostModificationEffect effect : costModificationEffects ) { + if ( effect.applies(abilityToModify, abilityMap.get(effect.getId()), game) ) { + effect.apply(game, abilityMap.get(effect.getId()), abilityToModify); + } + } + } + public boolean replaceEvent(GameEvent event, Game game) { boolean caught = false; List rEffects = getApplicableReplacementEffects(event, game); @@ -474,6 +514,11 @@ public class ContinuousEffects implements Serializable { asThoughEffects.add(newAsThoughEffect); abilityMap.put(newAsThoughEffect.getId(), source); break; + case COSTMODIFICATION: + CostModificationEffect newCostModificationEffect = (CostModificationEffect)effect; + costModificationEffects.add(newCostModificationEffect); + abilityMap.put(newCostModificationEffect.getId(), source); + break; default: ContinuousEffect newEffect = (ContinuousEffect)effect; layeredEffects.add(newEffect); diff --git a/Mage/src/mage/abilities/effects/CostModificationEffect.java b/Mage/src/mage/abilities/effects/CostModificationEffect.java new file mode 100644 index 0000000000..874e5bcc57 --- /dev/null +++ b/Mage/src/mage/abilities/effects/CostModificationEffect.java @@ -0,0 +1,67 @@ +/* + * 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; + +/** + * Represents a {@link ContinuousEffect} that will modify the cost of a spell or + * ability on the stack. {@link mage.abilities.Ability Abilities} with this type + * of effect will be called once and only once from the + * {@link mage.abilities.AbilityImpl#activate(mage.game.Game, boolean) Ability.activate} + * method before costs are paid. After this time the costs are locked in and + * should not be modified further. + * + * @author maurer.it_at_gmail.com + */ +//20101001 - 601.2e/613.10 +public interface CostModificationEffect> extends ContinuousEffect { + /** + * Called by the {@link ContinuousEffects#costModification(java.util.UUID, mage.abilities.Ability, mage.game.Game) ContinuousEffects.costModification} + * method. + * + * @param game The game for which this effect should be applied to. + * @param source The source ability of this effect. + * @param abilityToModify The {@link mage.abilities.SpellAbility} or {@link Ability} which should be modified. + * @return + */ + public boolean apply ( Game game, Ability source, Ability abilityToModify ); + + /** + * Called by the {@link ContinuousEffects#costModification(mage.abilities.Ability, mage.game.Game) ContinuousEffects.costModification} + * method. + * + * @param objectId The ability + * @param source + * @param game + * @return + */ + public boolean applies(Ability abilityToModify, Ability source, Game game); +} diff --git a/Mage/src/mage/abilities/effects/CostModificationEffectImpl.java b/Mage/src/mage/abilities/effects/CostModificationEffectImpl.java new file mode 100644 index 0000000000..0757173931 --- /dev/null +++ b/Mage/src/mage/abilities/effects/CostModificationEffectImpl.java @@ -0,0 +1,66 @@ +/* + * 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.Constants.Duration; +import mage.Constants.EffectType; +import mage.Constants.Outcome; +import mage.abilities.Ability; +import mage.game.Game; + +/** + * Simple implementation of a {@link CostModificationEffect} offering simplified + * construction to setup the object for use by the mage framework. + + * @author maurer.it_at_gmail.com + */ +public abstract class CostModificationEffectImpl> extends ContinuousEffectImpl implements CostModificationEffect { + + public CostModificationEffectImpl ( Duration duration, Outcome outcome ) { + super(duration, outcome); + this.effectType = EffectType.COSTMODIFICATION; + } + + public CostModificationEffectImpl(final CostModificationEffectImpl effect) { + super(effect); + this.effectType = effect.effectType; + } + + /** + * Overridden and 'no-op' implementation put in place. + * + * @see #apply(mage.game.Game, mage.abilities.Ability, mage.abilities.Ability) + * + * @param game + * @param source + * @return + */ + @Override + public final boolean apply ( Game game, Ability source ) { return false; } +}