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

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.game; package mage.game;
import mage.game.match.MatchImpl; import mage.game.match.MatchImpl;

View file

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

View file

@ -108,7 +108,7 @@ class AdmiralAckbarTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { 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 @Override

View file

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

View file

@ -49,6 +49,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.UntapAllControllerEffect; import mage.abilities.effects.common.UntapAllControllerEffect;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterNonlandPermanent; import mage.filter.common.FilterNonlandPermanent;
import mage.game.combat.CombatGroup;
import mage.players.Player; import mage.players.Player;
/** /**
@ -69,9 +70,7 @@ public class CurseOfBounty extends CardImpl {
// 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. // Each opponent attacking that player untaps all nonland permanents he or she controls.
Ability ability = new CurseOfBountyTriggeredAbility(); this.addAbility(new CurseOfBountyTriggeredAbility());
ability.addEffect(new UntapAllControllerEffect(new FilterNonlandPermanent()));
this.addAbility(ability);
} }
public CurseOfBounty(final CurseOfBounty card) { public CurseOfBounty(final CurseOfBounty card) {
@ -87,7 +86,7 @@ public class CurseOfBounty extends CardImpl {
class CurseOfBountyTriggeredAbility extends TriggeredAbilityImpl { class CurseOfBountyTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfBountyTriggeredAbility() { public CurseOfBountyTriggeredAbility() {
super(Zone.BATTLEFIELD, new UntapAllNonlandsTargetEffect(), false); super(Zone.BATTLEFIELD, new UntapAllControllerEffect(new FilterNonlandPermanent()), false);
} }
public CurseOfBountyTriggeredAbility(final CurseOfBountyTriggeredAbility ability) { public CurseOfBountyTriggeredAbility(final CurseOfBountyTriggeredAbility ability) {
@ -101,18 +100,22 @@ class CurseOfBountyTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId()); Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
UUID controller = this.getControllerId(); Player controller = game.getPlayer(getControllerId());
if (enchantment != null if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null && enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) { && game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) { for (CombatGroup group : game.getCombat().getBlockingGroups()) {
for (Effect effect: this.getEffects()) { if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId())); 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; return false;
} }

View file

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

View file

@ -27,10 +27,12 @@
*/ */
package mage.cards.c; package mage.cards.c;
import mage.abilities.Ability; import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect; 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.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -39,15 +41,14 @@ import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget; 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;
/** /**
* *
@ -66,9 +67,7 @@ public class CurseOfDisturbance extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget.getTargetName())); 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. // 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(); this.addAbility(new CurseOfDisturbanceTriggeredAbility());
ability.addEffect(new CreateTokenEffect(new ZombieToken()));
this.addAbility(ability);
} }
public CurseOfDisturbance(final CurseOfDisturbance card) { public CurseOfDisturbance(final CurseOfDisturbance card) {
@ -84,7 +83,7 @@ public class CurseOfDisturbance extends CardImpl {
class CurseOfDisturbanceTriggeredAbility extends TriggeredAbilityImpl { class CurseOfDisturbanceTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfDisturbanceTriggeredAbility() { public CurseOfDisturbanceTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenTargetEffect(new ZombieToken()), false); super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken()), false);
} }
public CurseOfDisturbanceTriggeredAbility(final CurseOfDisturbanceTriggeredAbility ability) { public CurseOfDisturbanceTriggeredAbility(final CurseOfDisturbanceTriggeredAbility ability) {
@ -98,18 +97,22 @@ class CurseOfDisturbanceTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId()); Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
UUID controller = this.getControllerId(); Player controller = game.getPlayer(getControllerId());
if (enchantment != null if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null && enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) { && game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) { for (CombatGroup group : game.getCombat().getBlockingGroups()) {
for (Effect effect: this.getEffects()) { if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId())); 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; return false;
} }

View file

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

View file

@ -27,10 +27,12 @@
*/ */
package mage.cards.c; package mage.cards.c;
import mage.abilities.Ability; import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect; 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.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -39,15 +41,14 @@ import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.token.GoldToken;
import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.target.targetpointer.FixedTarget; 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;
/** /**
* *
@ -67,9 +68,7 @@ public class CurseOfOpulence extends CardImpl {
// 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. // 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(); this.addAbility(new CurseOfOpulenceTriggeredAbility());
ability.addEffect(new CreateTokenEffect(new GoldToken()));
this.addAbility(ability);
} }
public CurseOfOpulence(final CurseOfOpulence card) { public CurseOfOpulence(final CurseOfOpulence card) {
@ -85,7 +84,7 @@ public class CurseOfOpulence extends CardImpl {
class CurseOfOpulenceTriggeredAbility extends TriggeredAbilityImpl { class CurseOfOpulenceTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfOpulenceTriggeredAbility() { public CurseOfOpulenceTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenTargetEffect(new GoldToken()), false); super(Zone.BATTLEFIELD, new CreateTokenEffect(new GoldToken()), false);
} }
public CurseOfOpulenceTriggeredAbility(final CurseOfOpulenceTriggeredAbility ability) { public CurseOfOpulenceTriggeredAbility(final CurseOfOpulenceTriggeredAbility ability) {
@ -99,18 +98,22 @@ class CurseOfOpulenceTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId()); Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
UUID controller = this.getControllerId(); Player controller = game.getPlayer(getControllerId());
if (enchantment != null if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null && enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) { && game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) { for (CombatGroup group : game.getCombat().getBlockingGroups()) {
for (Effect effect: this.getEffects()) { if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId())); 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; return false;
} }

View file

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

View file

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

View file

@ -27,7 +27,6 @@
*/ */
package mage.cards.c; package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.AttachEffect;
@ -47,6 +46,8 @@ import mage.target.targetpointer.FixedTarget;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.GainLifeTargetEffect; import mage.abilities.effects.common.GainLifeTargetEffect;
import mage.game.combat.CombatGroup;
import mage.players.Player;
/** /**
* *
@ -65,9 +66,7 @@ public class CurseOfVitality extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget.getTargetName())); this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
// Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same. // Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same.
Ability ability = new CurseOfVitalityTriggeredAbility(); this.addAbility(new CurseOfVitalityTriggeredAbility());
ability.addEffect(new GainLifeEffect(2));
this.addAbility(ability);
} }
public CurseOfVitality(final CurseOfVitality card) { public CurseOfVitality(final CurseOfVitality card) {
@ -83,7 +82,7 @@ public class CurseOfVitality extends CardImpl {
class CurseOfVitalityTriggeredAbility extends TriggeredAbilityImpl { class CurseOfVitalityTriggeredAbility extends TriggeredAbilityImpl {
public CurseOfVitalityTriggeredAbility() { public CurseOfVitalityTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeTargetEffect(2), false); super(Zone.BATTLEFIELD, new GainLifeEffect(2), false);
} }
public CurseOfVitalityTriggeredAbility(final CurseOfVitalityTriggeredAbility ability) { public CurseOfVitalityTriggeredAbility(final CurseOfVitalityTriggeredAbility ability) {
@ -97,18 +96,22 @@ class CurseOfVitalityTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId()); Permanent enchantment = game.getPermanentOrLKIBattlefield(getSourceId());
UUID controller = this.getControllerId(); Player controller = game.getPlayer(getControllerId());
if (enchantment != null if (controller != null && enchantment != null
&& enchantment.getAttachedTo() != null && enchantment.getAttachedTo() != null
&& game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) { && game.getCombat().getPlayerDefenders(game).contains(enchantment.getAttachedTo())) {
if (!game.getCombat().getAttackerId().equals(controller)) { for (CombatGroup group : game.getCombat().getBlockingGroups()) {
for (Effect effect: this.getEffects()) { if (group.getDefenderId().equals(enchantment.getAttachedTo())) {
effect.setTargetPointer(new FixedTarget(game.getCombat().getAttackerId())); 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; 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 @Override
public boolean checkTrigger(GameEvent event, Game game) { 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 @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("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("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("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 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("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("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)); cards.add(new SetCardInfo("Mirror of the Forebears", 54, Rarity.UNCOMMON, mage.cards.m.MirrorOfTheForebears.class));

View file

@ -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 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("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("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("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("Tremor", 99, Rarity.COMMON, mage.cards.t.Tremor.class));
cards.add(new SetCardInfo("Triangle of War", 158, Rarity.RARE, mage.cards.t.TriangleOfWar.class)); cards.add(new SetCardInfo("Triangle of War", 158, Rarity.RARE, mage.cards.t.TriangleOfWar.class));

View file

@ -56,7 +56,7 @@ public class AttacksWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
attackerCount++; attackerCount++;
} }
} }
return attackerCount >= minAttackers && game.getCombat().getAttackerId().equals(getControllerId()); return attackerCount >= minAttackers && game.getCombat().getAttackingPlayerId().equals(getControllerId());
} }
@Override @Override

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(); 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() { public Set<UUID> getDefenders() {
return defenders; return defenders;
} }
@ -1408,7 +1414,7 @@ public class Combat implements Serializable, Copyable<Combat> {
} }
} }
public UUID getAttackerId() { public UUID getAttackingPlayerId() {
return attackingPlayerId; return attackingPlayerId;
} }

View file

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