From 1b47a2fa8e4a151f4b627b4236e79e47379fb017 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 26 Dec 2012 20:42:37 +0100 Subject: [PATCH] Added DevourAbility, DevourEffect, needed Condition and DynamicValue. --- .../common/DevouredCreaturesCondition.java | 68 +++++++ .../common/DevouredCreaturesCount.java | 95 +++++++++ .../effects/common/DamageTargetEffect.java | 2 +- .../effects/common/DevourEffect.java | 184 ++++++++++++++++++ .../mage/abilities/keyword/DevourAbility.java | 85 ++++++++ 5 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 Mage/src/mage/abilities/condition/common/DevouredCreaturesCondition.java create mode 100644 Mage/src/mage/abilities/dynamicvalue/common/DevouredCreaturesCount.java create mode 100644 Mage/src/mage/abilities/effects/common/DevourEffect.java create mode 100644 Mage/src/mage/abilities/keyword/DevourAbility.java diff --git a/Mage/src/mage/abilities/condition/common/DevouredCreaturesCondition.java b/Mage/src/mage/abilities/condition/common/DevouredCreaturesCondition.java new file mode 100644 index 0000000000..3ae9f41844 --- /dev/null +++ b/Mage/src/mage/abilities/condition/common/DevouredCreaturesCondition.java @@ -0,0 +1,68 @@ +/* + * 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.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.condition.IntCompareCondition; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DevourEffect; +import mage.abilities.keyword.DevourAbility; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * Describes condition about how many creatures were devoured + * + * @author LevelX2 + */ +public class DevouredCreaturesCondition extends IntCompareCondition { + + public DevouredCreaturesCondition(Condition.ComparisonType type, int value) { + super(type, value); + } + + @Override + protected int getInputValue(Game game, Ability source) { + int devouredCreatures = 0; + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent != null) { + for (Ability ability : sourcePermanent.getAbilities()) { + if (ability instanceof DevourAbility) { + for (Effect effect: ability.getEffects()) { + if (effect instanceof DevourEffect) { + DevourEffect devourEffect = (DevourEffect) effect; + devouredCreatures = devourEffect.getDevouredCreaturesAmount(game, sourcePermanent.getId()); + } + } + } + } + } + return devouredCreatures; + } +} diff --git a/Mage/src/mage/abilities/dynamicvalue/common/DevouredCreaturesCount.java b/Mage/src/mage/abilities/dynamicvalue/common/DevouredCreaturesCount.java new file mode 100644 index 0000000000..0d530d515e --- /dev/null +++ b/Mage/src/mage/abilities/dynamicvalue/common/DevouredCreaturesCount.java @@ -0,0 +1,95 @@ +/* + * 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.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DevourEffect; +import mage.abilities.keyword.DevourAbility; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ + +public class DevouredCreaturesCount implements DynamicValue { + + int multiplier; + + public DevouredCreaturesCount() { + this(1); + } + + public DevouredCreaturesCount(int multiplier) { + super(); + this.multiplier = multiplier; + } + + public DevouredCreaturesCount(final DevouredCreaturesCount dynamicValue) { + super(); + this.multiplier = dynamicValue.multiplier; + } + + @Override + public int calculate(Game game, Ability sourceAbility) { + Permanent sourcePermanent = game.getPermanent(sourceAbility.getSourceId()); + if (sourcePermanent != null) { + for (Ability ability : sourcePermanent.getAbilities()) { + if (ability instanceof DevourAbility) { + for (Effect effect: ability.getEffects()) { + if (effect instanceof DevourEffect) { + DevourEffect devourEffect = (DevourEffect) effect; + return devourEffect.getDevouredCreaturesAmount(game, sourcePermanent.getId()) * multiplier; + } + } + + } + } + } + return 0; + } + + @Override + public DevouredCreaturesCount copy() { + return new DevouredCreaturesCount(this); + } + + @Override + public String toString() { + return Integer.toString(multiplier); + } + + @Override + public String getMessage() { + return "creature it devoured"; + } +} diff --git a/Mage/src/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/mage/abilities/effects/common/DamageTargetEffect.java index 15945ccbd2..105d81e319 100644 --- a/Mage/src/mage/abilities/effects/common/DamageTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/DamageTargetEffect.java @@ -134,7 +134,7 @@ public class DamageTargetEffect extends OneShotEffect { if (message.equals("1")) { sb.append(" equal to the number of "); } else { - if (message.startsWith("the")) { + if (message.startsWith("the") || message.startsWith("twice")) { sb.append(" equal to "); } else { sb.append(" for each "); diff --git a/Mage/src/mage/abilities/effects/common/DevourEffect.java b/Mage/src/mage/abilities/effects/common/DevourEffect.java new file mode 100644 index 0000000000..bbe8238f4d --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/DevourEffect.java @@ -0,0 +1,184 @@ +/* + * 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.common; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.Constants; +import mage.Constants.Outcome; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * Effect for the DevourAbility + * + * @author LevelX2 + */ +public class DevourEffect extends ReplacementEffectImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creatures to devour"); + static { + filter.add(new AnotherPredicate()); + } + private DevourFactor devourFactor; + + public enum DevourFactor { + Devour1 ("Devour 1", "that many +1/+1 counters on it", 1), + Devour2 ("Devour 2", "twice that many +1/+1 counters on it", 2), + Devour3 ("Devour 3", "three times that many +1/+1 counters on it", 3), + DevourX ("Devour X, where X is the number of creatures devoured this way", "X +1/+1 counters on it for each of those creatures", Integer.MAX_VALUE); + + private String text; + private String ruleText; + private int factor; + + DevourFactor(String text, String ruleText, int factor) { + this.text = text; + this.ruleText = ruleText; + this.factor = factor; + } + + @Override + public String toString() { + return text; + } + + public String getRuleText() { + return ruleText; + } + + public int getFactor() { + return factor; + } + } + + public DevourEffect(DevourFactor devourFactor) { + super(Constants.Duration.EndOfGame, Outcome.Detriment); + this.devourFactor = devourFactor; + } + + public DevourEffect(final DevourEffect effect) { + super(effect); + this.devourFactor = effect.devourFactor; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD + && event.getTargetId().equals(source.getSourceId())) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + game.getState().setValue(sourcePermanent.getId().toString() + "devoured", null); + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent creature = game.getPermanent(event.getTargetId()); + Player controller = game.getPlayer(source.getControllerId()); + if (creature != null && controller != null) { + Target target = new TargetControlledCreaturePermanent(1, Integer.MAX_VALUE, filter, true); + target.setRequired(false); + if (!target.canChoose(source.getSourceId(), source.getControllerId(), game)) { + return false; + } + if (controller.chooseUse(Outcome.Detriment, "Devour creatures?", game)) { + controller.chooseTarget(Outcome.Detriment, target, source, game); + if (target.getTargets().size() > 0) { + List> cardSubtypes = new ArrayList>(); + int devouredCreatures = target.getTargets().size(); + game.informPlayers(new StringBuilder(creature.getName()).append(" devours ").append(devouredCreatures).append(" creatures").toString()); + for (UUID targetId: target.getTargets()) { + Permanent targetCreature = game.getPermanent(targetId); + cardSubtypes.add((ArrayList) targetCreature.getSubtype()); + if (targetCreature == null || !targetCreature.sacrifice(source.getSourceId(), game)) { + return false; + } + } + int amountCounters; + if (devourFactor == DevourFactor.DevourX) { + amountCounters = devouredCreatures * devouredCreatures; + } else { + amountCounters = devouredCreatures * devourFactor.getFactor(); + } + creature.addCounters(CounterType.P1P1.createInstance(amountCounters), game); + game.getState().setValue(creature.getId().toString() + "devoured", cardSubtypes); + } + + } + return true; + } + return false; + } + + @Override + public String getText(Mode mode) { + StringBuilder sb = new StringBuilder(devourFactor.toString()); + sb.append(" (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with "); + sb.append(devourFactor.getRuleText()).append(")"); + return sb.toString(); + } + + public List> getSubtypes(Game game, UUID permanentId) { + Object object = game.getState().getValue(permanentId.toString() + "devoured"); + if (object != null) { + return (List>) object; + } + return null; + } + + public int getDevouredCreaturesAmount(Game game, UUID permanentId) { + Object object = game.getState().getValue(permanentId.toString() + "devoured"); + if (object != null) { + return ((List>) object).size(); + } + return 0; + } + + @Override + public DevourEffect copy() { + return new DevourEffect(this); + } +} diff --git a/Mage/src/mage/abilities/keyword/DevourAbility.java b/Mage/src/mage/abilities/keyword/DevourAbility.java new file mode 100644 index 0000000000..bde3a81c05 --- /dev/null +++ b/Mage/src/mage/abilities/keyword/DevourAbility.java @@ -0,0 +1,85 @@ +/* + * 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.keyword; + +import mage.Constants.Zone; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DevourEffect; +import mage.abilities.effects.common.DevourEffect.DevourFactor; + +/** + * 502.82. Devour + * + * 502.82a Devour is a static ability. "Devour N" means "As this object comes into play, + * you may sacrifice any number of creatures. This permanent comes into play with N +1/+1 + * counters on it for each creature sacrificed this way." + * + * 502.82b Some objects have abilities that refer to the number of creatures the permanent + * devoured. "It devoured" means "sacrificed as a result of its devour ability as it came + * into play." + * + * Devour appears only on creature cards. + * + * A creature with devour can devour other creatures no matter how it comes into play. + * + * You may choose to not sacrifice any creatures. + * + * If you play a creature with devour as a spell, you choose how many and which creatures + * to devour as part of the resolution of that spell. (It can't be countered at this point.) + * The same is true of a spell or ability that lets you put a creature with devour into play. + * + * You may sacrifice only creatures that are already in play. If a creature with devour and + * another creature are coming into play under your control at the same time, the creature + * with devour can't devour that other creature. The creature with devour also can't devour + * itself. + * + * If multiple creatures with devour are coming into play under your control at the same time, + * you may use each one's devour ability. A creature you already control can be devoured by + * only one of them, however. (In other words, you can't sacrifice the same creature to satisfy + * multiple devour abilities.) All creatures devoured this way are sacrificed at the same time. + * + * @author LevelX2 + */ + + public class DevourAbility extends SimpleStaticAbility { + + + + public DevourAbility(DevourFactor devourFactor) { + super(Zone.BATTLEFIELD, new DevourEffect(devourFactor)); + } + + public DevourAbility(final DevourAbility ability) { + super(ability); + } + + @Override + public DevourAbility copy() { + return new DevourAbility(this); + } +} \ No newline at end of file