mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
Much better than revision 4e7269ad70
This commit is contained in:
parent
2fb0b267bf
commit
31fedb27a6
6 changed files with 220 additions and 29 deletions
|
@ -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<EyeofUgin> {
|
|||
}
|
||||
}
|
||||
|
||||
class EyeofUginCostReductionEffect extends ContinuousEffectImpl<EyeofUginCostReductionEffect> {
|
||||
class EyeofUginCostReductionEffect extends CostModificationEffectImpl<EyeofUginCostReductionEffect> {
|
||||
|
||||
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<EyeofUginCostRed
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
SpellStack stack = game.getStack();
|
||||
boolean applied = false;
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
SpellAbility spellAbility = (SpellAbility)abilityToModify;
|
||||
int previousCost = spellAbility.getManaCostsToPay().convertedManaCost();
|
||||
int adjustedCost = 0;
|
||||
if ( (previousCost - 2) > 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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
|
|||
protected UUID controllerId;
|
||||
protected UUID sourceId;
|
||||
protected ManaCosts<ManaCost> manaCosts;
|
||||
protected ManaCosts<ManaCost> manaCostsToPay;
|
||||
protected Costs<Cost> costs;
|
||||
protected ArrayList<AlternativeCost> alternativeCosts = new ArrayList<AlternativeCost>();
|
||||
protected Costs<Cost> optionalCosts;
|
||||
|
@ -87,6 +88,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
|
|||
this.abilityType = abilityType;
|
||||
this.zone = zone;
|
||||
this.manaCosts = new ManaCostsImpl<ManaCost>();
|
||||
this.manaCostsToPay = new ManaCostsImpl<ManaCost>();
|
||||
this.costs = new CostsImpl<Cost>();
|
||||
this.optionalCosts = new CostsImpl<Cost>();
|
||||
this.effects = new Effects();
|
||||
|
@ -104,6 +106,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> 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<T extends AbilityImpl<T>> 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<T extends AbilityImpl<T>> 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<ManaCost> getManaCostsToPay ( ) {
|
||||
return manaCostsToPay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AlternativeCost> getAlternativeCosts() {
|
||||
return alternativeCosts;
|
||||
|
@ -324,6 +340,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
|
|||
public void addManaCost(ManaCost cost) {
|
||||
if (cost != null) {
|
||||
this.manaCosts.add(cost);
|
||||
this.manaCostsToPay.add(cost);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ public class ContinuousEffects implements Serializable {
|
|||
private final List<RequirementEffect> requirementEffects = new ArrayList<RequirementEffect>();
|
||||
private final List<RestrictionEffect> restrictionEffects = new ArrayList<RestrictionEffect>();
|
||||
private final List<AsThoughEffect> asThoughEffects = new ArrayList<AsThoughEffect>();
|
||||
private final List<CostModificationEffect> costModificationEffects = new ArrayList<CostModificationEffect>();
|
||||
|
||||
//map Abilities to Continuous effects
|
||||
private final Map<UUID, Ability> abilityMap = new HashMap<UUID, Ability>();
|
||||
|
@ -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<UUID, Ability> 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<CostModificationEffect> 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<CostModificationEffect> 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<ReplacementEffect> 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);
|
||||
|
|
67
Mage/src/mage/abilities/effects/CostModificationEffect.java
Normal file
67
Mage/src/mage/abilities/effects/CostModificationEffect.java
Normal file
|
@ -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<T extends CostModificationEffect<T>> extends ContinuousEffect<T> {
|
||||
/**
|
||||
* 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);
|
||||
}
|
|
@ -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<T extends CostModificationEffectImpl<T>> extends ContinuousEffectImpl<T> implements CostModificationEffect<T> {
|
||||
|
||||
public CostModificationEffectImpl ( Duration duration, Outcome outcome ) {
|
||||
super(duration, outcome);
|
||||
this.effectType = EffectType.COSTMODIFICATION;
|
||||
}
|
||||
|
||||
public CostModificationEffectImpl(final CostModificationEffectImpl<T> 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; }
|
||||
}
|
Loading…
Reference in a new issue