Merge pull request #33 from magefree/master

merge
This commit is contained in:
theelk801 2017-08-17 15:55:26 -04:00 committed by GitHub
commit b2270a7f10
24 changed files with 990 additions and 171 deletions

View file

@ -1,16 +1,16 @@
/*
* 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
@ -20,12 +20,11 @@
* 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.game;
import mage.game.match.MatchImpl;
@ -43,7 +42,7 @@ public class TwoPlayerMatch extends MatchImpl {
@Override
public void startGame() throws GameException {
TwoPlayerDuel game = new TwoPlayerDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(),20);
TwoPlayerDuel game = new TwoPlayerDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), 20);
// Sets a start message about the match score
game.setStartMessage(this.createGameStartMessage());
initGame(game);

View file

@ -158,7 +158,7 @@ public final class CombatUtil {
public static CombatInfo blockWithGoodTrade(Game game, List<Permanent> attackers, List<Permanent> blockers) {
UUID attackerId = game.getCombat().getAttackerId();
UUID attackerId = game.getCombat().getAttackingPlayerId();
UUID defenderId = game.getCombat().getDefenders().iterator().next();
if (attackerId == null || defenderId == null) {
log.warn("Couldn't find attacker or defender: " + attackerId + ' ' + defenderId);
@ -295,7 +295,7 @@ public final class CombatUtil {
public static CombatInfo blockWithGoodTrade2(Game game, List<Permanent> attackers, List<Permanent> blockers) {
UUID attackerId = game.getCombat().getAttackerId();
UUID attackerId = game.getCombat().getAttackingPlayerId();
UUID defenderId = game.getCombat().getDefenders().iterator().next();
if (attackerId == null || defenderId == null) {
log.warn("Couldn't find attacker or defender: " + attackerId + ' ' + defenderId);

View file

@ -108,7 +108,7 @@ class AdmiralAckbarTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return game.getCombat().getAttackers().size() >= 2 && game.getCombat().getAttackerId().equals(getControllerId());
return game.getCombat().getAttackers().size() >= 2 && game.getCombat().getAttackingPlayerId().equals(getControllerId());
}
@Override

View file

@ -84,7 +84,7 @@ public class CitadelSiege extends CardImpl {
public void adjustTargets(Ability ability, Game game) {
if (this.getAbilities().contains(ability) && ability.getRule().startsWith("&bull Dragons")) {
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature that player controls");
filter.add(new ControllerIdPredicate(game.getCombat().getAttackerId()));
filter.add(new ControllerIdPredicate(game.getCombat().getAttackingPlayerId()));
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanent(filter));
}

View file

@ -49,6 +49,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.UntapAllControllerEffect;
import mage.filter.StaticFilters;
import mage.filter.common.FilterNonlandPermanent;
import mage.game.combat.CombatGroup;
import mage.players.Player;
/**
@ -58,7 +59,7 @@ import mage.players.Player;
public class CurseOfBounty extends CardImpl {
public CurseOfBounty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
this.subtype.add(SubType.AURA, SubType.CURSE);
// Enchant player
@ -67,11 +68,9 @@ public class CurseOfBounty extends CardImpl {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted player is attacked, untap all nonland permanents you control.
// Whenever enchanted player is attacked, untap all nonland permanents you control.
// Each opponent attacking that player untaps all nonland permanents he or she controls.
Ability ability = new CurseOfBountyTriggeredAbility();
ability.addEffect(new UntapAllControllerEffect(new FilterNonlandPermanent()));
this.addAbility(ability);
this.addAbility(new CurseOfBountyTriggeredAbility());
}
public CurseOfBounty(final CurseOfBounty card) {
@ -87,7 +86,7 @@ public class CurseOfBounty extends CardImpl {
class CurseOfBountyTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfBountyTriggeredAbility() {
super(Zone.BATTLEFIELD, new UntapAllNonlandsTargetEffect(), false);
super(Zone.BATTLEFIELD, new UntapAllControllerEffect(new FilterNonlandPermanent()), false);
}
public CurseOfBountyTriggeredAbility(final CurseOfBountyTriggeredAbility ability) {
@ -101,17 +100,21 @@ class CurseOfBountyTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
UUID controller = this.getControllerId();
if (enchantment != null
Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
Player controller = game.getPlayer(getControllerId());
if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) {
for (Effect effect: this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
if (controller.hasOpponent(game.getCombat().getAttackingPlayerId(), game)) {
Effect effect = new UntapAllNonlandsTargetEffect();
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
this.addEffect(effect);
}
return true;
}
}
return true;
}
return false;
}
@ -129,7 +132,7 @@ class CurseOfBountyTriggeredAbility extends TriggeredAbilityImpl {
}
class UntapAllNonlandsTargetEffect extends OneShotEffect {
public UntapAllNonlandsTargetEffect() {
super(Outcome.Untap);
}
@ -142,7 +145,7 @@ class UntapAllNonlandsTargetEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (player != null) {
for (Permanent nonland: game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_NON_LAND, player.getId(), game)) {
for (Permanent nonland : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_NON_LAND, player.getId(), game)) {
nonland.untap(game);
}
return true;

View file

@ -102,7 +102,7 @@ class CurseOfChaosTriggeredAbility extends TriggeredAbilityImpl {
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
for (Effect effect: this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
}
return true;
}

View file

@ -27,10 +27,12 @@
*/
package mage.cards.c;
import mage.abilities.Ability;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.CreateTokenTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -39,15 +41,14 @@ import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.CreateTokenTargetEffect;
import mage.game.permanent.token.ZombieToken;
/**
*
@ -56,7 +57,7 @@ import mage.game.permanent.token.ZombieToken;
public class CurseOfDisturbance extends CardImpl {
public CurseOfDisturbance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
this.subtype.add(SubType.AURA, SubType.CURSE);
// Enchant player
@ -66,9 +67,7 @@ public class CurseOfDisturbance extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same.
Ability ability = new CurseOfDisturbanceTriggeredAbility();
ability.addEffect(new CreateTokenEffect(new ZombieToken()));
this.addAbility(ability);
this.addAbility(new CurseOfDisturbanceTriggeredAbility());
}
public CurseOfDisturbance(final CurseOfDisturbance card) {
@ -84,7 +83,7 @@ public class CurseOfDisturbance extends CardImpl {
class CurseOfDisturbanceTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfDisturbanceTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenTargetEffect(new ZombieToken()), false);
super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken()), false);
}
public CurseOfDisturbanceTriggeredAbility(final CurseOfDisturbanceTriggeredAbility ability) {
@ -98,17 +97,21 @@ class CurseOfDisturbanceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
UUID controller = this.getControllerId();
if (enchantment != null
Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
Player controller = game.getPlayer(getControllerId());
if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) {
for (Effect effect: this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
if (controller.hasOpponent(game.getCombat().getAttackingPlayerId(), game)) {
Effect effect = new CreateTokenTargetEffect(new ZombieToken());
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
this.addEffect(effect);
}
return true;
}
}
return true;
}
return false;
}
@ -122,5 +125,5 @@ class CurseOfDisturbanceTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfDisturbanceTriggeredAbility copy() {
return new CurseOfDisturbanceTriggeredAbility(this);
}
}

View file

@ -102,7 +102,7 @@ class CurseOfInertiaTriggeredAbility extends TriggeredAbilityImpl {
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
TargetPermanent target = new TargetPermanent();
target.setTargetController(game.getCombat().getAttackerId());
target.setTargetController(game.getCombat().getAttackingPlayerId());
addTarget(target);
return true;
}

View file

@ -27,10 +27,12 @@
*/
package mage.cards.c;
import mage.abilities.Ability;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.CreateTokenTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -39,15 +41,14 @@ import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.GoldToken;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.CreateTokenTargetEffect;
import mage.game.permanent.token.GoldToken;
/**
*
@ -56,7 +57,7 @@ import mage.game.permanent.token.GoldToken;
public class CurseOfOpulence extends CardImpl {
public CurseOfOpulence(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}");
this.subtype.add(SubType.AURA, SubType.CURSE);
// Enchant player
@ -65,11 +66,9 @@ public class CurseOfOpulence extends CardImpl {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted player is attacked, create a colorless artifact token named Gold.
// Whenever enchanted player is attacked, create a colorless artifact token named Gold.
// It has "sacrifice this artifact: Add one mana of any color to your mana pool." Each opponent attacking that player does the same.
Ability ability = new CurseOfOpulenceTriggeredAbility();
ability.addEffect(new CreateTokenEffect(new GoldToken()));
this.addAbility(ability);
this.addAbility(new CurseOfOpulenceTriggeredAbility());
}
public CurseOfOpulence(final CurseOfOpulence card) {
@ -85,7 +84,7 @@ public class CurseOfOpulence extends CardImpl {
class CurseOfOpulenceTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfOpulenceTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenTargetEffect(new GoldToken()), false);
super(Zone.BATTLEFIELD, new CreateTokenEffect(new GoldToken()), false);
}
public CurseOfOpulenceTriggeredAbility(final CurseOfOpulenceTriggeredAbility ability) {
@ -99,17 +98,21 @@ class CurseOfOpulenceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
UUID controller = this.getControllerId();
if (enchantment != null
Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
Player controller = game.getPlayer(getControllerId());
if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) {
for (Effect effect: this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
if (controller.hasOpponent(game.getCombat().getAttackingPlayerId(), game)) {
Effect effect = new CreateTokenTargetEffect(new GoldToken());
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
this.addEffect(effect);
}
return true;
}
}
return true;
}
return false;
}
@ -124,5 +127,5 @@ class CurseOfOpulenceTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfOpulenceTriggeredAbility copy() {
return new CurseOfOpulenceTriggeredAbility(this);
}
}

View file

@ -108,7 +108,7 @@ class CurseOfShallowTriggeredAbility extends TriggeredAbilityImpl {
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
}
return true;
}

View file

@ -27,10 +27,12 @@
*/
package mage.cards.c;
import mage.abilities.Ability;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.DrawCardTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -39,14 +41,13 @@ import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.DrawCardTargetEffect;
/**
*
@ -55,7 +56,7 @@ import mage.abilities.effects.common.DrawCardTargetEffect;
public class CurseOfVerbosity extends CardImpl {
public CurseOfVerbosity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
this.subtype.add(SubType.AURA, SubType.CURSE);
// Enchant player
@ -65,9 +66,7 @@ public class CurseOfVerbosity extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted player is attacked, draw a card. Each opponent attacking that player does the same.
Ability ability = new CurseOfVerbosityTriggeredAbility();
ability.addEffect(new DrawCardSourceControllerEffect(1));
this.addAbility(ability);
this.addAbility(new CurseOfVerbosityTriggeredAbility());
}
public CurseOfVerbosity(final CurseOfVerbosity card) {
@ -83,7 +82,7 @@ public class CurseOfVerbosity extends CardImpl {
class CurseOfVerbosityTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfVerbosityTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardTargetEffect(1), false);
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false);
}
public CurseOfVerbosityTriggeredAbility(final CurseOfVerbosityTriggeredAbility ability) {
@ -97,17 +96,21 @@ class CurseOfVerbosityTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
UUID controller = this.getControllerId();
if (enchantment != null
Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
Player controller = game.getPlayer(getControllerId());
if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) {
for (Effect effect: this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
if (controller.hasOpponent(game.getCombat().getAttackingPlayerId(), game)) {
Effect effect = new DrawCardTargetEffect(1);
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
this.addEffect(effect);
}
return true;
}
}
return true;
}
return false;
}

View file

@ -27,7 +27,6 @@
*/
package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
@ -47,6 +46,8 @@ import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.GainLifeTargetEffect;
import mage.game.combat.CombatGroup;
import mage.players.Player;
/**
*
@ -55,7 +56,7 @@ import mage.abilities.effects.common.GainLifeTargetEffect;
public class CurseOfVitality extends CardImpl {
public CurseOfVitality(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
this.subtype.add(SubType.AURA, SubType.CURSE);
// Enchant player
@ -65,9 +66,7 @@ public class CurseOfVitality extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same.
Ability ability = new CurseOfVitalityTriggeredAbility();
ability.addEffect(new GainLifeEffect(2));
this.addAbility(ability);
this.addAbility(new CurseOfVitalityTriggeredAbility());
}
public CurseOfVitality(final CurseOfVitality card) {
@ -83,7 +82,7 @@ public class CurseOfVitality extends CardImpl {
class CurseOfVitalityTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfVitalityTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeTargetEffect(2), false);
super(Zone.BATTLEFIELD, new GainLifeEffect(2), false);
}
public CurseOfVitalityTriggeredAbility(final CurseOfVitalityTriggeredAbility ability) {
@ -97,17 +96,21 @@ class CurseOfVitalityTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId());
UUID controller = this.getControllerId();
if (enchantment != null
Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
Player controller = game.getPlayer(getControllerId());
if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) {
for (Effect effect: this.getEffects()) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId()));
for (CombatGroup group : game.getCombat().getBlockingGroups()) {
if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
if (controller.hasOpponent(game.getCombat().getAttackingPlayerId(), game)) {
Effect effect = new GainLifeTargetEffect(2);
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackingPlayerId()));
this.addEffect(effect);
}
return true;
}
}
return true;
}
return false;
}

View file

@ -0,0 +1,90 @@
/*
* 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.cards.k;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
import mage.filter.predicate.permanent.CounterPredicate;
import mage.target.TargetPermanent;
/**
*
* @author Saga
*/
public class KindredBoon extends CardImpl {
private static final FilterControlledCreaturePermanent filterDivinity = new FilterControlledCreaturePermanent("Each creature you control with a divinity counter on it");
static {
filterDivinity.add(new CounterPredicate(CounterType.DIVINITY));
}
public KindredBoon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}");
// As Kindred Boon enters the battlefield, choose a creature type.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.AddAbility)));
// {1}{W}: Put a divinity counter on target creature you control of the chosen type.
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control of the chosen type");
filter.add(new ChosenSubtypePredicate(this.getId()));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.DIVINITY.createInstance()), new ManaCostsImpl("{1}{W}"));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
// Each creature you control with a divinity counter on it has indestructible.
Effect effect = new GainAbilityControlledEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield, filterDivinity);
effect.setText("Each creature you control with a divinity counter on it has indestructible");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public KindredBoon(final KindredBoon card) {
super(card);
}
@Override
public KindredBoon copy() {
return new KindredBoon(this);
}
}

View file

@ -0,0 +1,117 @@
/*
* 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.cards.k;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.PutTokenOntoBattlefieldCopyTargetEffect;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author Saga
*/
public class KindredCharge extends CardImpl {
public KindredCharge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}");
// Choose a creature type. For each creature you control of the chosen type, create a token that's a copy of that creature.
// Those tokens gain haste. Exile them at the beginning of the next end step.
this.getSpellAbility().addEffect(new ChooseCreatureTypeEffect(Outcome.Copy));
this.getSpellAbility().addEffect(new KindredChargeEffect());
}
public KindredCharge(final KindredCharge card) {
super(card);
}
@Override
public KindredCharge copy() {
return new KindredCharge(this);
}
}
class KindredChargeEffect extends OneShotEffect {
public KindredChargeEffect() {
super(Outcome.Copy);
this.staticText = "For each creature you control of the chosen type, create a token that's a copy of that creature. "
+ "Those tokens gain haste. Exile them at the beginning of the next end step";
}
public KindredChargeEffect(final KindredChargeEffect effect) {
super(effect);
}
@Override
public KindredChargeEffect copy() {
return new KindredChargeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null && sourceObject != null) {
String creatureType = game.getState().getValue(sourceObject.getId() + "_type").toString();
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control of the chosen type");
filter.add(new SubtypePredicate(SubType.byDescription(creatureType)));
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) {
if (permanent != null) {
PutTokenOntoBattlefieldCopyTargetEffect effect = new PutTokenOntoBattlefieldCopyTargetEffect(source.getControllerId(), null, true);
effect.setTargetPointer(new FixedTarget(permanent, game));
effect.apply(game, source);
for (Permanent addedToken : effect.getAddedPermanent()) {
Effect exileEffect = new ExileTargetEffect();
exileEffect.setTargetPointer(new FixedTarget(addedToken, game));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect), source);
}
}
}
return true;
}
return false;
}
}

View file

@ -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.cards.k;
import java.util.UUID;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.EntersBattlefieldOrAttacksAllTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
/**
*
* @author Saga
*/
public class KindredDiscovery extends CardImpl {
public KindredDiscovery(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}{U}");
// As Kindred Discovery enters the battlefield, choose a creature type.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.DrawCard)));
// Whenever a creature you control of the chosen type enters the battlefield or attacks, draw a card.
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature you control of the chosen type");
filter.add(new ChosenSubtypePredicate(this.getId()));
this.addAbility(new EntersBattlefieldOrAttacksAllTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, false));
}
public KindredDiscovery(final KindredDiscovery card) {
super(card);
}
@Override
public KindredDiscovery copy() {
return new KindredDiscovery(this);
}
}

View file

@ -0,0 +1,126 @@
/*
* 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.cards.k;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author Saga
*/
public class KindredSummons extends CardImpl {
public KindredSummons(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{5}{G}{G}");
// Choose a creature type. Reveal cards from the top of your library until you reveal X creature cards of the chosen type,
// where X is the number of creatures you control of that type. Put those cards onto the battlefield,
// then shuffle the rest of the revealed cards into your library.
this.getSpellAbility().addEffect(new ChooseCreatureTypeEffect(Outcome.PutCreatureInPlay));
this.getSpellAbility().addEffect(new KindredSummonsEffect());
}
public KindredSummons(final KindredSummons card) {
super(card);
}
@Override
public KindredSummons copy() {
return new KindredSummons(this);
}
}
class KindredSummonsEffect extends OneShotEffect {
public KindredSummonsEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "Reveal cards from the top of your library until you reveal X creature cards of the chosen type, " +
"where X is the number of creatures you control of that type. Put those cards onto the battlefield, "
+ "then shuffle the rest of the revealed cards into your library";
}
public KindredSummonsEffect(final KindredSummonsEffect effect) {
super(effect);
}
@Override
public KindredSummonsEffect copy() {
return new KindredSummonsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
String creatureType = game.getState().getValue(sourceObject.getId() + "_type").toString();
FilterControlledCreaturePermanent filterPermanent = new FilterControlledCreaturePermanent("creature you control of the chosen type");
filterPermanent.add(new SubtypePredicate(SubType.byDescription(creatureType)));
int numberOfCards = game.getBattlefield().countAll(filterPermanent, source.getControllerId(), game);
Cards revealed = new CardsImpl();
Set<Card> chosenSubtypeCreatureCards = new LinkedHashSet<>();
Cards otherCards = new CardsImpl();
FilterCreatureCard filterCard = new FilterCreatureCard("creature card of the chosen type");
filterCard.add(new SubtypePredicate(SubType.byDescription(creatureType)));
while (chosenSubtypeCreatureCards.size() < numberOfCards && controller.getLibrary().hasCards()) {
Card card = controller.getLibrary().removeFromTop(game);
revealed.add(card);
if (card != null && filterCard.match(card, game)) {
chosenSubtypeCreatureCards.add(card);
} else {
otherCards.add(card);
}
}
controller.revealCards(sourceObject.getIdName(), revealed, game);
controller.moveCards(chosenSubtypeCreatureCards, Zone.BATTLEFIELD, source, game, false, false, false, null);
controller.putCardsOnTopOfLibrary(otherCards, game, source, false);
controller.shuffleLibrary(source, game);
return true;
}
return false;
}
}

View file

@ -83,7 +83,7 @@ class OverwhelmingInstinctTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return game.getCombat().getAttackers().size() >= 3 && game.getCombat().getAttackerId().equals(getControllerId());
return game.getCombat().getAttackers().size() >= 3 && game.getCombat().getAttackingPlayerId().equals(getControllerId());
}
@Override

View file

@ -0,0 +1,220 @@
/*
* 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.cards.t;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
*
* @author jeffwadsworth
*/
public class ThreeWishes extends CardImpl {
public ThreeWishes(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}");
// Exile the top three cards of your library face down. You may look at those cards for as long as they remain exiled. Until your next turn, you may play those cards. At the beginning of your next upkeep, put any of those cards you didn't play into your graveyard.
this.getSpellAbility().addEffect(new ThreeWishesExileEffect());
this.addAbility(new SimpleStaticAbility(Zone.ALL, new ThreeWishesLookAtCardEffect()));
}
public ThreeWishes(final ThreeWishes card) {
super(card);
}
@Override
public ThreeWishes copy() {
return new ThreeWishes(this);
}
}
class ThreeWishesExileEffect extends OneShotEffect {
public ThreeWishesExileEffect() {
super(Outcome.DrawCard);
staticText = "Exile the top three cards of your library face down. Until your next turn, you may play those cards. At the beginning of your next upkeep, put any of those cards you didn't play into your graveyard";
}
public ThreeWishesExileEffect(final ThreeWishesExileEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), 0);
Set<Card> topThreeCards = controller.getLibrary().getTopCards(game, 3);
for (Card card : topThreeCards) {
if (controller.moveCardsToExile(card, source, game, true, exileId, "Three Wishes")) {
card.setFaceDown(true, game);
ContinuousEffect effect = new ThreeWishesPlayFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
}
}
DelayedTriggeredAbility delayed = new AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility(new ThreeWishesPutIntoGraveyardEffect());
game.addDelayedTriggeredAbility(delayed, source);
return true;
}
return false;
}
@Override
public ThreeWishesExileEffect copy() {
return new ThreeWishesExileEffect(this);
}
}
class ThreeWishesPutIntoGraveyardEffect extends OneShotEffect {
public ThreeWishesPutIntoGraveyardEffect() {
super(Outcome.Neutral);
staticText = "At the beginning of your next upkeep, put any of those cards you didn't play into your graveyard";
}
public ThreeWishesPutIntoGraveyardEffect(final ThreeWishesPutIntoGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), 0);
Set<Card> cardsInExile = game.getExile().getExileZone(exileId).getCards(game);
if (cardsInExile != null) {
controller.moveCardsToGraveyardWithInfo(cardsInExile, source, game, Zone.EXILED);
return true;
}
}
return false;
}
@Override
public ThreeWishesPutIntoGraveyardEffect copy() {
return new ThreeWishesPutIntoGraveyardEffect(this);
}
}
class ThreeWishesLookAtCardEffect extends AsThoughEffectImpl {
public ThreeWishesLookAtCardEffect() {
super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.Custom, Outcome.Benefit);
staticText = "You may look at cards exiled with {this} as long as they remain exiled";
}
public ThreeWishesLookAtCardEffect(final ThreeWishesLookAtCardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public ThreeWishesLookAtCardEffect copy() {
return new ThreeWishesLookAtCardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (affectedControllerId.equals(source.getControllerId())) {
Card card = game.getCard(objectId);
if (card != null) {
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject == null) {
return false;
}
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), 0);
ExileZone exile = game.getExile().getExileZone(exileId);
return exile != null
&& exile.contains(card.getId());
}
}
return false;
}
}
class ThreeWishesPlayFromExileEffect extends AsThoughEffectImpl {
ThreeWishesPlayFromExileEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.UntilYourNextTurn, Outcome.Benefit);
staticText = "Until your next turn, you may play those cards";
}
ThreeWishesPlayFromExileEffect(final ThreeWishesPlayFromExileEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public ThreeWishesPlayFromExileEffect copy() {
return new ThreeWishesPlayFromExileEffect(this);
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), 0);
ExileZone exile = game.getExile().getExileZone(exileId);
return exile != null
&& getTargetPointer().getFirst(game, source) != null
&& getTargetPointer().getFirst(game, source).equals(sourceId)
&& source.getControllerId().equals(affectedControllerId)
&& game.getState().getZone(sourceId) == Zone.EXILED
&& exile.contains(sourceId);
}
}

View file

@ -68,7 +68,11 @@ public class Commander2017 extends ExpansionSet {
cards.add(new SetCardInfo("Inalla, Archmage Ritualist", 38, Rarity.MYTHIC, mage.cards.i.InallaArchmageRitualist.class));
cards.add(new SetCardInfo("Izzet Chemister", 26, Rarity.RARE, mage.cards.i.IzzetChemister.class));
cards.add(new SetCardInfo("Kheru Mind-Eater", 17, Rarity.RARE, mage.cards.k.KheruMindEater.class));
cards.add(new SetCardInfo("Kindred Boon", 5, Rarity.RARE, mage.cards.k.KindredBoon.class));
cards.add(new SetCardInfo("Kindred Charge", 27, Rarity.RARE, mage.cards.k.KindredCharge.class));
cards.add(new SetCardInfo("Kindred Discovery", 11, Rarity.RARE, mage.cards.k.KindredDiscovery.class));
cards.add(new SetCardInfo("Kindred Dominance", 18, Rarity.RARE, mage.cards.k.KindredDominance.class));
cards.add(new SetCardInfo("Kindred Summons", 32, Rarity.RARE, mage.cards.k.KindredSummons.class));
cards.add(new SetCardInfo("Magus of the Mind", 12, Rarity.RARE, mage.cards.m.MagusOfTheMind.class));
cards.add(new SetCardInfo("Mirri, Weatherlight Duelist", 43, Rarity.MYTHIC, mage.cards.m.MirriWeatherlightDuelist.class));
cards.add(new SetCardInfo("Mirror of the Forebears", 54, Rarity.UNCOMMON, mage.cards.m.MirrorOfTheForebears.class));

View file

@ -59,7 +59,7 @@ public class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Army Ants", 126, Rarity.UNCOMMON, mage.cards.a.ArmyAnts.class));
cards.add(new SetCardInfo("Betrayal", 26, Rarity.COMMON, mage.cards.b.Betrayal.class));
cards.add(new SetCardInfo("Blanket of Night", 2, Rarity.UNCOMMON, mage.cards.b.BlanketOfNight.class));
cards.add(new SetCardInfo("Brass-Talon Chimera", 142, Rarity.UNCOMMON, mage.cards.b.BrassTalonChimera.class));
cards.add(new SetCardInfo("Brass-Talon Chimera", 142, Rarity.UNCOMMON, mage.cards.b.BrassTalonChimera.class));
cards.add(new SetCardInfo("Breathstealer's Crypt", 127, Rarity.RARE, mage.cards.b.BreathstealersCrypt.class));
cards.add(new SetCardInfo("Breezekeeper", 27, Rarity.COMMON, mage.cards.b.Breezekeeper.class));
cards.add(new SetCardInfo("Bull Elephant", 51, Rarity.COMMON, mage.cards.b.BullElephant.class));
@ -163,6 +163,7 @@ public class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Teferi's Puzzle Box", 156, Rarity.RARE, mage.cards.t.TeferisPuzzleBox.class));
cards.add(new SetCardInfo("Teferi's Realm", 44, Rarity.RARE, mage.cards.t.TeferisRealm.class));
cards.add(new SetCardInfo("Tempest Drake", 139, Rarity.UNCOMMON, mage.cards.t.TempestDrake.class));
cards.add(new SetCardInfo("Three Wishes", 45, Rarity.RARE, mage.cards.t.ThreeWishes.class));
cards.add(new SetCardInfo("Tithe", 123, Rarity.RARE, mage.cards.t.Tithe.class));
cards.add(new SetCardInfo("Tremor", 99, Rarity.COMMON, mage.cards.t.Tremor.class));
cards.add(new SetCardInfo("Triangle of War", 158, Rarity.RARE, mage.cards.t.TriangleOfWar.class));

View file

@ -1,71 +1,71 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.common;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
*
* @author Styxo
*/
public class AttacksWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
private FilterCreaturePermanent filter;
private int minAttackers;
public AttacksWithCreaturesTriggeredAbility(Effect effect, int minAttackers) {
this(effect, minAttackers, new FilterCreaturePermanent("creatures"));
}
public AttacksWithCreaturesTriggeredAbility(Effect effect, int minAttackers, FilterCreaturePermanent filter) {
super(Zone.BATTLEFIELD, effect);
this.filter = filter;
this.minAttackers = minAttackers;
}
public AttacksWithCreaturesTriggeredAbility(final AttacksWithCreaturesTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.minAttackers = ability.minAttackers;
}
@Override
public AttacksWithCreaturesTriggeredAbility copy() {
return new AttacksWithCreaturesTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
int attackerCount = 0;
for (UUID attacker : game.getCombat().getAttackers()) {
if (filter.match(game.getPermanent(attacker), game)) {
attackerCount++;
}
}
return attackerCount >= minAttackers && game.getCombat().getAttackerId().equals(getControllerId());
}
@Override
public String getRule() {
StringBuilder sb = new StringBuilder("Whenever you attack with " + minAttackers + " or more ");
sb.append(filter.getMessage());
sb.append(", ");
sb.append(super.getRule());
return sb.toString();
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.common;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
*
* @author Styxo
*/
public class AttacksWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
private FilterCreaturePermanent filter;
private int minAttackers;
public AttacksWithCreaturesTriggeredAbility(Effect effect, int minAttackers) {
this(effect, minAttackers, new FilterCreaturePermanent("creatures"));
}
public AttacksWithCreaturesTriggeredAbility(Effect effect, int minAttackers, FilterCreaturePermanent filter) {
super(Zone.BATTLEFIELD, effect);
this.filter = filter;
this.minAttackers = minAttackers;
}
public AttacksWithCreaturesTriggeredAbility(final AttacksWithCreaturesTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.minAttackers = ability.minAttackers;
}
@Override
public AttacksWithCreaturesTriggeredAbility copy() {
return new AttacksWithCreaturesTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
int attackerCount = 0;
for (UUID attacker : game.getCombat().getAttackers()) {
if (filter.match(game.getPermanent(attacker), game)) {
attackerCount++;
}
}
return attackerCount >= minAttackers && game.getCombat().getAttackingPlayerId().equals(getControllerId());
}
@Override
public String getRule() {
StringBuilder sb = new StringBuilder("Whenever you attack with " + minAttackers + " or more ");
sb.append(filter.getMessage());
sb.append(", ");
sb.append(super.getRule());
return sb.toString();
}
}

View file

@ -0,0 +1,168 @@
/*
* 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.common;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author Saga
*/
public class EntersBattlefieldOrAttacksAllTriggeredAbility extends TriggeredAbilityImpl {
protected FilterPermanent filter;
protected String rule;
protected boolean controlledText;
protected SetTargetPointer setTargetPointer;
/**
* zone = BATTLEFIELD optional = false
*
* @param effect
* @param filter
*/
public EntersBattlefieldOrAttacksAllTriggeredAbility(Effect effect, FilterPermanent filter) {
this(Zone.BATTLEFIELD, effect, filter, false);
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(Effect effect, FilterPermanent filter, String rule) {
this(Zone.BATTLEFIELD, effect, filter, false, rule);
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional) {
this(zone, effect, filter, optional, SetTargetPointer.NONE, null, false);
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule) {
this(zone, effect, filter, optional, rule, false);
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule, boolean controlledText) {
this(zone, effect, filter, optional, SetTargetPointer.NONE, rule, controlledText);
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule) {
this(zone, effect, filter, optional, setTargetPointer, rule, false);
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule, boolean controlledText) {
super(zone, effect, optional);
this.filter = filter;
this.rule = rule;
this.controlledText = controlledText;
this.setTargetPointer = setTargetPointer;
}
public EntersBattlefieldOrAttacksAllTriggeredAbility(final EntersBattlefieldOrAttacksAllTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.rule = ability.rule;
this.controlledText = ability.controlledText;
this.setTargetPointer = ability.setTargetPointer;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD || event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
Permanent attacker = game.getPermanent(event.getSourceId());
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD
&& permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) {
if (setTargetPointer != SetTargetPointer.NONE) {
for (Effect effect : this.getEffects()) {
switch (setTargetPointer) {
case PERMANENT:
effect.setTargetPointer(new FixedTarget(permanent, game));
break;
case PLAYER:
effect.setTargetPointer(new FixedTarget(permanent.getControllerId()));
break;
}
}
}
return true;
}
if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED
&& attacker != null && filter.match(attacker, getSourceId(), getControllerId(), game)) {
if (setTargetPointer != SetTargetPointer.NONE) {
for (Effect effect : this.getEffects()) {
switch (setTargetPointer) {
case PERMANENT:
effect.setTargetPointer(new FixedTarget(attacker.getId()));
break;
case PLAYER:
UUID playerId = controlledText ? attacker.getControllerId() : game.getCombat().getDefendingPlayerId(attacker.getId(), game);
if (playerId != null) {
effect.setTargetPointer(new FixedTarget(playerId));
}
break;
}
}
}
return true;
}
return false;
}
@Override
public String getRule() {
if (rule != null && !rule.isEmpty()) {
return rule;
}
StringBuilder sb = new StringBuilder("Whenever ").append(filter.getMessage());
sb.append(" enters the battlefield ");
if (controlledText) {
sb.append("under your control, ");
} else {
sb.append("or attacks, ");
}
sb.append(super.getRule());
return sb.toString();
}
@Override
public EntersBattlefieldOrAttacksAllTriggeredAbility copy() {
return new EntersBattlefieldOrAttacksAllTriggeredAbility(this);
}
}

View file

@ -118,6 +118,12 @@ public class Combat implements Serializable, Copyable<Combat> {
return blockingGroups.values();
}
/**
* Get all possible defender (players and plainwalkers) That does not mean
* neccessarly mean that they are really attacked
*
* @return
*/
public Set<UUID> getDefenders() {
return defenders;
}
@ -1408,7 +1414,7 @@ public class Combat implements Serializable, Copyable<Combat> {
}
}
public UUID getAttackerId() {
public UUID getAttackingPlayerId() {
return attackingPlayerId;
}

View file

@ -168,8 +168,13 @@ public abstract class MatchImpl implements Match {
MatchPlayer matchWinner = null;
for (MatchPlayer matchPlayer : players) {
if (!matchPlayer.hasQuit()) {
activePlayers++;
matchWinner = matchPlayer;
if (matchPlayer.getDeck() == null) {
logger.error("MatchPlayer's deck was null - matchId " + this.getId() + " - " + matchPlayer.getName());
matchPlayer.setQuit(true);
} else {
activePlayers++;
matchWinner = matchPlayer;
}
}
if (matchPlayer.getWins() >= options.getWinsNeeded()) {
matchPlayer.setMatchWinner(true);