mirror of
https://github.com/correl/mage.git
synced 2024-11-15 19:19:33 +00:00
Merge branch 'master' of https://github.com/magefree/mage.git
This commit is contained in:
commit
aae4b019f6
6 changed files with 633 additions and 18 deletions
155
Mage.Sets/src/mage/sets/theros/PolukranosWorldEater.java
Normal file
155
Mage.Sets/src/mage/sets/theros/PolukranosWorldEater.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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.sets.theros;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.MonstrosityAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCreaturePermanentAmount;
|
||||
|
||||
/**
|
||||
*
|
||||
* * The value of X in Polukranos’s last ability is equal to the value chosen
|
||||
* for X when its activated ability was activated.
|
||||
*
|
||||
* * The number of targets chosen for the triggered ability must be at least one
|
||||
* (if X wasn’t 0) and at most X. You choose the division of damage as you put
|
||||
* the ability on the stack, not as it resolves. Each target must be assigned
|
||||
* at least 1 damage. In multiplayer games, you may choose creatures controlled
|
||||
* by different opponents.
|
||||
*
|
||||
* * If some, but not all, of the ability’s targets become illegal, you can’t change
|
||||
* the division of damage. Damage that would’ve been dealt to illegal targets
|
||||
* simply isn’t dealt.
|
||||
*
|
||||
* * As Polukranos’s triggered ability resolves, Polukranos deals damage first, then
|
||||
* the target creatures do. Although no creature will die until after the ability
|
||||
* finishes resolving, the order could matter if Polukranos has wither or infect.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class PolukranosWorldEater extends CardImpl<PolukranosWorldEater> {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
static {
|
||||
filter.add(new ControllerPredicate(TargetController.OPPONENT));
|
||||
}
|
||||
|
||||
public PolukranosWorldEater(UUID ownerId) {
|
||||
super(ownerId, 172, "Polukranos, World Eater", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
|
||||
this.expansionSetCode = "THS";
|
||||
this.supertype.add("Legendary");
|
||||
this.subtype.add("Hydra");
|
||||
|
||||
this.color.setGreen(true);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// {X}{X}{G}: Monstrosity X.
|
||||
this.addAbility(new MonstrosityAbility("{X}{X}{G}", Integer.MAX_VALUE));
|
||||
// When Polukranos, World Eater becomes monstrous, it deals X damage divided as you choose among any number of target creatures your opponents control. Each of those creatures deals damage equal to its power to Polukranos.
|
||||
Ability ability = new BecomesMonstrousSourceTriggeredAbility(new PolukranosWorldEaterEffect());
|
||||
ability.addTarget(new TargetCreaturePermanentAmount(1, filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (ability instanceof BecomesMonstrousSourceTriggeredAbility) {
|
||||
int xValue = ((BecomesMonstrousSourceTriggeredAbility) ability).getMonstrosityValue();
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetCreaturePermanentAmount(xValue, filter));
|
||||
}
|
||||
}
|
||||
|
||||
public PolukranosWorldEater(final PolukranosWorldEater card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolukranosWorldEater copy() {
|
||||
return new PolukranosWorldEater(this);
|
||||
}
|
||||
}
|
||||
|
||||
class PolukranosWorldEaterEffect extends OneShotEffect<PolukranosWorldEaterEffect> {
|
||||
|
||||
public PolukranosWorldEaterEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "it deals X damage divided as you choose among any number of target creatures your opponents control. Each of those creatures deals damage equal to its power to Polukranos";
|
||||
}
|
||||
|
||||
public PolukranosWorldEaterEffect(final PolukranosWorldEaterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolukranosWorldEaterEffect copy() {
|
||||
return new PolukranosWorldEaterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (source.getTargets().size() > 0) {
|
||||
Target multiTarget = source.getTargets().get(0);
|
||||
Set<Permanent> permanents = new HashSet<Permanent>();
|
||||
for (UUID target: multiTarget.getTargets()) {
|
||||
Permanent permanent = game.getPermanent(target);
|
||||
if (permanent != null) {
|
||||
permanents.add(permanent);
|
||||
permanent.damage(multiTarget.getTargetAmount(target), source.getSourceId(), game, true, false);
|
||||
}
|
||||
}
|
||||
// Each of those creatures deals damage equal to its power to Polukranos
|
||||
Permanent sourceCreature = game.getPermanent(source.getSourceId());
|
||||
if (sourceCreature != null) {
|
||||
for (Permanent permanent :permanents) {
|
||||
sourceCreature.damage(permanent.getPower().getValue(), source.getSourceId(), game, true, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
272
Mage.Sets/src/mage/sets/theros/RescueFromTheUnderworld.java
Normal file
272
Mage.Sets/src/mage/sets/theros/RescueFromTheUnderworld.java
Normal file
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* 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.sets.theros;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ExileSourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
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.TargetCardInGraveyard;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* Once you announce you’re casting Rescue from the Underworld, no player may attempt to
|
||||
* stop you from casting the spell by removing the creature you want to sacrifice.
|
||||
*
|
||||
* If you sacrifice a creature token to cast Rescue from the Underworld, it won’t return
|
||||
* to the battlefield, although the target creature card will.
|
||||
*
|
||||
* If either the sacrificed creature or the target creature card leaves the graveyard
|
||||
* before the delayed triggered ability resolves during your next upkeep, it won’t return.
|
||||
*
|
||||
* However, if the sacrificed creature is put into another public zone instead of the graveyard,
|
||||
* perhaps because it’s your commander or because of another replacement effect, it will return
|
||||
* to the battlefield from the zone it went to.
|
||||
*
|
||||
* Rescue from the Underworld is exiled as it resolves, not later as its delayed trigger resolves.
|
||||
*
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RescueFromTheUnderworld extends CardImpl<RescueFromTheUnderworld> {
|
||||
|
||||
public RescueFromTheUnderworld(UUID ownerId) {
|
||||
super(ownerId, 102, "Rescue from the Underworld", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{4}{B}");
|
||||
this.expansionSetCode = "THS";
|
||||
|
||||
this.color.setBlack(true);
|
||||
|
||||
// As an additional cost to cast Rescue from the Underworld, sacrifice a creature.
|
||||
this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent()));
|
||||
|
||||
// Choose target creature card in your graveyard. Return that card and the sacrificed card to the battlefield under your control at the beginning of your next upkeep. Exile Rescue from the Underworld.
|
||||
this.getSpellAbility().addEffect(new RescueFromTheUnderworldTextEffect());
|
||||
this.getSpellAbility().addEffect(new RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(new RescueFromTheUnderworldDelayedTriggeredAbility()));
|
||||
Target target = new TargetCardInYourGraveyard(new FilterCreatureCard("creature card in your graveyard"));
|
||||
target.setRequired(true);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
this.getSpellAbility().addEffect(new ExileSourceEffect());
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworld(final RescueFromTheUnderworld card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RescueFromTheUnderworld copy() {
|
||||
return new RescueFromTheUnderworld(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RescueFromTheUnderworldTextEffect extends OneShotEffect<RescueFromTheUnderworldTextEffect> {
|
||||
|
||||
public RescueFromTheUnderworldTextEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Choose target creature card in your graveyard";
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworldTextEffect(final RescueFromTheUnderworldTextEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RescueFromTheUnderworldTextEffect copy() {
|
||||
return new RescueFromTheUnderworldTextEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect extends OneShotEffect<RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect> {
|
||||
|
||||
protected DelayedTriggeredAbility ability;
|
||||
|
||||
public RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability) {
|
||||
super(ability.getEffects().get(0).getOutcome());
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(final RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect effect) {
|
||||
super(effect);
|
||||
this.ability = effect.ability.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect copy() {
|
||||
return new RescueFromTheUnderworldCreateDelayedTriggeredAbilityEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
DelayedTriggeredAbility delayedAbility = (DelayedTriggeredAbility) ability.copy();
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
delayedAbility.getTargets().addAll(source.getTargets());
|
||||
for(Effect effect : delayedAbility.getEffects()) {
|
||||
effect.getTargetPointer().init(game, source);
|
||||
}
|
||||
// add the scraificed creature as target
|
||||
for (Cost cost :source.getCosts()) {
|
||||
if (cost instanceof SacrificeTargetCost) {
|
||||
SacrificeTargetCost sacCost = (SacrificeTargetCost) cost;
|
||||
TargetCardInGraveyard target = new TargetCardInGraveyard();
|
||||
for(Permanent permanent : sacCost.getPermanents()) {
|
||||
target.add(permanent.getId(), game);
|
||||
delayedAbility.getTargets().add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
return ability.getRule();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RescueFromTheUnderworldDelayedTriggeredAbility extends DelayedTriggeredAbility<RescueFromTheUnderworldDelayedTriggeredAbility> {
|
||||
|
||||
public RescueFromTheUnderworldDelayedTriggeredAbility() {
|
||||
this(new RescueFromTheUnderworldReturnEffect(), TargetController.YOU);
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworldDelayedTriggeredAbility(Effect effect, TargetController targetController) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworldDelayedTriggeredAbility(RescueFromTheUnderworldDelayedTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE && event.getPlayerId().equals(this.controllerId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RescueFromTheUnderworldDelayedTriggeredAbility copy() {
|
||||
return new RescueFromTheUnderworldDelayedTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Return that card and the sacrificed card to the battlefield under your control at the beginning of your next upkeep";
|
||||
}
|
||||
}
|
||||
|
||||
class RescueFromTheUnderworldReturnEffect extends OneShotEffect<RescueFromTheUnderworldReturnEffect> {
|
||||
|
||||
private boolean tapped;
|
||||
|
||||
public RescueFromTheUnderworldReturnEffect() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworldReturnEffect(boolean tapped) {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
this.tapped = tapped;
|
||||
}
|
||||
|
||||
public RescueFromTheUnderworldReturnEffect(final RescueFromTheUnderworldReturnEffect effect) {
|
||||
super(effect);
|
||||
this.tapped = effect.tapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RescueFromTheUnderworldReturnEffect copy() {
|
||||
return new RescueFromTheUnderworldReturnEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
boolean result = false;
|
||||
// Target card comes only back if in graveyard
|
||||
for (UUID targetId: getTargetPointer().getTargets(game, source)) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null) {
|
||||
Player player = game.getPlayer(card.getOwnerId());
|
||||
if (player != null) {
|
||||
if(card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId(), tapped)){
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// However, if the sacrificed creature is put into another public zone instead of the graveyard,
|
||||
// perhaps because it’s your commander or because of another replacement effect, it will return
|
||||
// to the battlefield from the zone it went to.
|
||||
if (source.getTargets().get(1) != null) {
|
||||
for (UUID targetId: ((Target) source.getTargets().get(1)).getTargets()) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null && !card.isFaceDown()) {
|
||||
Player player = game.getPlayer(card.getOwnerId());
|
||||
if (player != null) {
|
||||
Zone currentZone = game.getState().getZone(card.getId());
|
||||
if (currentZone.equals(Zone.COMMAND) || currentZone.equals(Zone.GRAVEYARD) || currentZone.equals(Zone.EXILED)) {
|
||||
if(card.putOntoBattlefield(game, currentZone, source.getSourceId(), source.getControllerId(), false)){
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
151
Mage.Sets/src/mage/sets/theros/TimeToFeed.java
Normal file
151
Mage.Sets/src/mage/sets/theros/TimeToFeed.java
Normal file
|
@ -0,0 +1,151 @@
|
|||
|
||||
/*
|
||||
* 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.sets.theros;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.FightTargetsEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
/**
|
||||
* Time to Feed has two targets: a creature an opponent controls and a creature you control.
|
||||
* If only one of those creatures is a legal target when Time to Feed tries to resolve, the
|
||||
* creatures won’t fight and neither will deal or be dealt damage. However, you’ll still gain
|
||||
* 3 life when the creature you don’t control dies that turn, even if it was the illegal target as Time to Feed resolved.
|
||||
* If neither creature is a legal target when Time to Feed tries to resolve, the spell will
|
||||
* be countered and none of its effects will happen.
|
||||
* If the first target creature dies that turn, you’ll gain 3 life no matter what caused the creature to die or who controls the creature at that time.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TimeToFeed extends CardImpl<TimeToFeed> {
|
||||
|
||||
private static final FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature an opponent controls");
|
||||
static {
|
||||
filter1.add(new ControllerPredicate(TargetController.OPPONENT));
|
||||
}
|
||||
|
||||
public TimeToFeed(UUID ownerId) {
|
||||
super(ownerId, 181, "Time to Feed", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}");
|
||||
this.expansionSetCode = "THS";
|
||||
|
||||
this.color.setGreen(true);
|
||||
|
||||
// Choose target creature an opponent controls. When that creature dies this turn, you gain 3 life. Target creature you control fights that creature.
|
||||
this.getSpellAbility().addEffect(new TimeToFeedTextEffect());
|
||||
Target target = new TargetCreaturePermanent(filter1);
|
||||
target.setRequired(true);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(true));
|
||||
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new TimeToFeedDiesTargetTriggeredAbility()));
|
||||
Effect effect = new FightTargetsEffect();
|
||||
effect.setText("Target creature you control fights that creature");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
}
|
||||
|
||||
public TimeToFeed(final TimeToFeed card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeToFeed copy() {
|
||||
return new TimeToFeed(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TimeToFeedTextEffect extends OneShotEffect<TimeToFeedTextEffect> {
|
||||
|
||||
public TimeToFeedTextEffect() {
|
||||
super(Outcome.Detriment);
|
||||
this.staticText = "Choose target creature an opponent controls";
|
||||
}
|
||||
|
||||
public TimeToFeedTextEffect(final TimeToFeedTextEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeToFeedTextEffect copy() {
|
||||
return new TimeToFeedTextEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class TimeToFeedDiesTargetTriggeredAbility extends DelayedTriggeredAbility<TimeToFeedDiesTargetTriggeredAbility> {
|
||||
|
||||
public TimeToFeedDiesTargetTriggeredAbility() {
|
||||
super(new GainLifeEffect(3), Duration.EndOfTurn, false);
|
||||
}
|
||||
|
||||
public TimeToFeedDiesTargetTriggeredAbility(final TimeToFeedDiesTargetTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeToFeedDiesTargetTriggeredAbility copy() {
|
||||
return new TimeToFeedDiesTargetTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) {
|
||||
if (event.getTargetId().equals(getEffects().get(0).getTargetPointer().getFirst(game, this))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When that creature dies this turn, " + super.getRule();
|
||||
}
|
||||
}
|
|
@ -40,12 +40,15 @@ import mage.game.events.GameEvent.EventType;
|
|||
*/
|
||||
public class BecomesMonstrousSourceTriggeredAbility extends TriggeredAbilityImpl<BecomesMonstrousSourceTriggeredAbility> {
|
||||
|
||||
private int monstrosityValue;
|
||||
|
||||
public BecomesMonstrousSourceTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect, false);
|
||||
}
|
||||
|
||||
public BecomesMonstrousSourceTriggeredAbility(final BecomesMonstrousSourceTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.monstrosityValue = ability.monstrosityValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,11 +59,16 @@ public class BecomesMonstrousSourceTriggeredAbility extends TriggeredAbilityImpl
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType().equals(EventType.BECOMES_MONSTROUS) && event.getSourceId().equals(this.getSourceId())) {
|
||||
this.monstrosityValue = event.getAmount();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getMonstrosityValue() {
|
||||
return monstrosityValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} becomes monstrous, " + super.getRule();
|
||||
|
|
|
@ -72,8 +72,8 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect<CreateDel
|
|||
delayedAbility.setControllerId(source.getControllerId());
|
||||
if (this.copyTargets) {
|
||||
delayedAbility.getTargets().addAll(source.getTargets());
|
||||
for(Effect effect : ability.getEffects()) {
|
||||
effect.setTargetPointer(targetPointer);
|
||||
for(Effect effect : delayedAbility.getEffects()) {
|
||||
effect.getTargetPointer().init(game, source);
|
||||
}
|
||||
}
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
|
|
|
@ -30,10 +30,7 @@ package mage.abilities.keyword;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.condition.InvertCondition;
|
||||
import mage.abilities.condition.common.MonstrousCondition;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.constants.Outcome;
|
||||
|
@ -44,8 +41,29 @@ import mage.game.events.GameEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Monstrosity
|
||||
*
|
||||
* 701.28. Monstrosity
|
||||
*
|
||||
* 701.28a “Monstrosity N” means “If this permanent isn’t monstrous, put N +1/+1 counters on it
|
||||
* and it becomes monstrous.” Monstrous is a condition of that permanent that can be
|
||||
* referred to by other abilities.
|
||||
*
|
||||
* 701.28b If a permanent’s ability instructs a player to “monstrosity X,” other abilities of
|
||||
* that permanent may also refer to X. The value of X in those abilities is equal to
|
||||
* the value of X as that permanent became monstrous.
|
||||
*
|
||||
* * Once a creature becomes monstrous, it can’t become monstrous again. If the creature
|
||||
* is already monstrous when the monstrosity ability resolves, nothing happens.
|
||||
*
|
||||
* * Monstrous isn’t an ability that a creature has. It’s just something true about that
|
||||
* creature. If the creature stops being a creature or loses its abilities, it will
|
||||
* continue to be monstrous.
|
||||
*
|
||||
* * An ability that triggers when a creature becomes monstrous won’t trigger if that creature
|
||||
* isn’t on the battlefield when its monstrosity ability resolves.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
@ -54,15 +72,13 @@ public class MonstrosityAbility extends ActivatedAbilityImpl<MonstrosityAbility>
|
|||
|
||||
private int monstrosityValue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param manaString
|
||||
* @param monstrosityValue use Integer.MAX_VALUE for monstrosity X.
|
||||
*/
|
||||
public MonstrosityAbility(String manaString, int monstrosityValue) {
|
||||
super(Zone.BATTLEFIELD, new ConditionalOneShotEffect(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(monstrosityValue)),
|
||||
new InvertCondition(MonstrousCondition.getInstance()),
|
||||
""), new ManaCostsImpl(manaString));
|
||||
this.addEffect(new ConditionalOneShotEffect(
|
||||
new BecomeMonstrousSourceEffect(),
|
||||
new InvertCondition(MonstrousCondition.getInstance()),""));
|
||||
|
||||
super(Zone.BATTLEFIELD, new BecomeMonstrousSourceEffect(),new ManaCostsImpl(manaString));
|
||||
this.monstrosityValue = monstrosityValue;
|
||||
}
|
||||
|
||||
|
@ -78,13 +94,20 @@ public class MonstrosityAbility extends ActivatedAbilityImpl<MonstrosityAbility>
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return new StringBuilder(manaCosts.getText()).append(": Monstrosity ").append(monstrosityValue)
|
||||
.append(". <i>(If this creature isn't monstrous, put ").append(CardUtil.numberToText(monstrosityValue))
|
||||
return new StringBuilder(manaCosts.getText()).append(": Monstrosity ")
|
||||
.append(monstrosityValue == Integer.MAX_VALUE ? "X":monstrosityValue)
|
||||
.append(". <i>(If this creature isn't monstrous, put ")
|
||||
.append(monstrosityValue == Integer.MAX_VALUE ? "X":CardUtil.numberToText(monstrosityValue))
|
||||
.append(" +1/+1 counters on it and it becomes monstrous.)</i>").toString();
|
||||
}
|
||||
|
||||
}
|
||||
public int getMonstrosityValue() {
|
||||
return monstrosityValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
class BecomeMonstrousSourceEffect extends OneShotEffect<BecomeMonstrousSourceEffect> {
|
||||
|
||||
public BecomeMonstrousSourceEffect() {
|
||||
|
@ -104,9 +127,15 @@ class BecomeMonstrousSourceEffect extends OneShotEffect<BecomeMonstrousSourceEff
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
if (permanent != null && !permanent.isMonstrous() && source instanceof MonstrosityAbility) {
|
||||
int monstrosityValue = ((MonstrosityAbility) source).getMonstrosityValue();
|
||||
// handle monstrosity = X
|
||||
if (monstrosityValue == Integer.MAX_VALUE) {
|
||||
monstrosityValue = source.getManaCostsToPay().getX();
|
||||
}
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(monstrosityValue)).apply(game, source);
|
||||
permanent.setMonstrous(true);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_MONSTROUS, source.getSourceId(), source.getSourceId(), source.getControllerId()));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BECOMES_MONSTROUS, source.getSourceId(), source.getSourceId(), source.getControllerId(), monstrosityValue));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue