forked from External/mage
master #8
18 changed files with 378 additions and 195 deletions
|
|
@ -4,4 +4,4 @@ set JAVA_HOME="C:\Program Files\Java\jre7\"
|
|||
set CLASSPATH=%JAVA_HOME%/bin;%CLASSPATH%
|
||||
set PATH=%JAVA_HOME%/bin;%PATH%
|
||||
:NOJAVADIR
|
||||
java -Xmx1024m -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -jar .\lib\mage-client-${project.version}.jar
|
||||
java -Xmx2000m -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -jar .\lib\mage-client-${project.version}.jar
|
||||
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
java -Xmx1024m -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -jar ./lib/mage-client-${project.version}.jar &
|
||||
java -Xmx2000m -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -jar ./lib/mage-client-${project.version}.jar &
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
java -Xmx1024m -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -jar ./lib/mage-client-${project.version}.jar &
|
||||
java -Xmx2000m -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -jar ./lib/mage-client-${project.version}.jar &
|
||||
|
|
@ -4,4 +4,4 @@ set JAVA_HOME="C:\Program Files (x86)\Java\jre7\"
|
|||
set CLASSPATH=%JAVA_HOME%/bin;%CLASSPATH%
|
||||
set PATH=%JAVA_HOME%/bin;%PATH%
|
||||
:NOJAVADIR
|
||||
java -Xmx1024m -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -jar .\lib\mage-client-${project.version}.jar
|
||||
java -Xmx2000m -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -jar .\lib\mage-client-${project.version}.jar
|
||||
|
|
@ -1502,7 +1502,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
if (!Charset.defaultCharset().toString().equals("UTF-8")) {
|
||||
LOGGER.warn("WARNING, bad charset. Some images will not be downloaded. You must:");
|
||||
LOGGER.warn("* Open launcher -> settings -> java -> client java options");
|
||||
LOGGER.warn("* Insert additional command at the the end: -Dfile.encoding=UTF-8");
|
||||
LOGGER.warn("* Insert at the the end: -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8");
|
||||
}
|
||||
|
||||
startTime = System.currentTimeMillis();
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class ComeBackWrongEffect extends OneShotEffect {
|
|||
permanent.destroy(source, game);
|
||||
// tokens are not creature cards
|
||||
if (permanent instanceof PermanentToken) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
Card card = permanent.getMainCard();
|
||||
if (card == null
|
||||
|
|
@ -78,11 +78,11 @@ class ComeBackWrongEffect extends OneShotEffect {
|
|||
}
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
player.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
Permanent creature = game.getPermanent(card.getId());
|
||||
if (permanent != null) {
|
||||
if (creature != null) {
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfPlayersNextEndStepDelayedTriggeredAbility(
|
||||
new SacrificeTargetEffect("sacrifice it")
|
||||
.setTargetPointer(new FixedTarget(creature, game)),
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class FirstResponderEffect extends OneShotEffect {
|
|||
player.moveCards(permanent, Zone.HAND, source, game);
|
||||
int power = permanent.getPower().getValue();
|
||||
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (power < 1 || sourcePermanent == null) {
|
||||
if (power > 0 && sourcePermanent != null) {
|
||||
sourcePermanent.addCounters(CounterType.P1P1.createInstance(power), source, game);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
121
Mage.Sets/src/mage/cards/h/Hezrou.java
Normal file
121
Mage.Sets/src/mage/cards/h/Hezrou.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||
import mage.cards.AdventureCard;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.BlockedThisTurnPredicate;
|
||||
import mage.filter.predicate.permanent.BlockingPredicate;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.common.BlockedThisTurnWatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author xenohedron
|
||||
*/
|
||||
public final class Hezrou extends AdventureCard {
|
||||
|
||||
private static final FilterCreaturePermanent filterBlocked = new FilterCreaturePermanent("each creature that blocked this turn");
|
||||
private static final FilterCreaturePermanent filterBlocking = new FilterCreaturePermanent("each blocking creature");
|
||||
static {
|
||||
filterBlocked.add(BlockedThisTurnPredicate.instance);
|
||||
filterBlocking.add(BlockingPredicate.instance);
|
||||
}
|
||||
|
||||
|
||||
public Hezrou(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.INSTANT}, "{5}{B}{B}", "Demonic Stench", "{B}");
|
||||
|
||||
this.subtype.add(SubType.FROG);
|
||||
this.subtype.add(SubType.DEMON);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// Whenever one or more creatures you control become blocked, each blocking creature gets -1/-1 until end of turn.
|
||||
this.addAbility(new HezrouTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn, filterBlocking, false)));
|
||||
|
||||
// Demonic Stench
|
||||
// Each creature that blocked this turn gets -1/-1 until end of turn.
|
||||
this.getSpellCard().getSpellAbility().addEffect(new BoostAllEffect(-1, -1, Duration.EndOfTurn, filterBlocked, false));
|
||||
this.getSpellCard().getSpellAbility().addWatcher(new BlockedThisTurnWatcher());
|
||||
|
||||
this.finalizeAdventure();
|
||||
}
|
||||
|
||||
private Hezrou(final Hezrou card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hezrou copy() {
|
||||
return new Hezrou(this);
|
||||
}
|
||||
}
|
||||
|
||||
class HezrouTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
HezrouTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect);
|
||||
setTriggerPhrase("Whenever one or more creatures you control become blocked, ");
|
||||
}
|
||||
|
||||
private HezrouTriggeredAbility(final HezrouTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DECLARE_BLOCKERS_STEP
|
||||
|| event.getType() == GameEvent.EventType.BATCH_BLOCK_NONCOMBAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case DECLARE_BLOCKERS_STEP:
|
||||
return game.getCombat()
|
||||
.getGroups()
|
||||
.stream()
|
||||
.filter(CombatGroup::getBlocked)
|
||||
.map(CombatGroup::getAttackers)
|
||||
.flatMap(Collection::stream)
|
||||
.map(game::getControllerId)
|
||||
.anyMatch(this.getControllerId()::equals);
|
||||
case BATCH_BLOCK_NONCOMBAT:
|
||||
Object value = game.getState().getValue("becameBlocked_" + event.getData());
|
||||
if (!(value instanceof Set)) {
|
||||
return false;
|
||||
}
|
||||
Set<MageObjectReference> permanents = (Set<MageObjectReference>) value;
|
||||
return permanents
|
||||
.stream()
|
||||
.map(mor -> mor.getPermanentOrLKIBattlefield(game))
|
||||
.filter(Objects::nonNull)
|
||||
.map(Controllable::getControllerId)
|
||||
.anyMatch(this.getControllerId()::equals);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HezrouTriggeredAbility copy() {
|
||||
return new HezrouTriggeredAbility(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ enum LightPawsEmperorsVoicePredicate implements Predicate<Permanent> {
|
|||
|
||||
class LightPawsEmperorsVoiceEffect extends OneShotEffect {
|
||||
|
||||
private static enum LightPawsEmperorsVoiceEffectPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
private enum LightPawsEmperorsVoiceEffectPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
instance;
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.AURA);
|
||||
|
||||
|
|
|
|||
112
Mage.Sets/src/mage/cards/m/MirrorOfLifeTrapping.java
Normal file
112
Mage.Sets/src/mage/cards/m/MirrorOfLifeTrapping.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author xenohedron
|
||||
*/
|
||||
public final class MirrorOfLifeTrapping extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature");
|
||||
static {
|
||||
filter.add(MirrorOfLifeTrappingCastPredicate.instance);
|
||||
}
|
||||
|
||||
public MirrorOfLifeTrapping(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
|
||||
|
||||
// Whenever a creature enters, if it was cast, exile it, then return all other permanent cards exiled with Mirror of Life Trapping to the battlefield under their owners' control.
|
||||
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new MirrorOfLifeTrappingEffect(),
|
||||
filter, false, SetTargetPointer.PERMANENT));
|
||||
}
|
||||
|
||||
private MirrorOfLifeTrapping(final MirrorOfLifeTrapping card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MirrorOfLifeTrapping copy() {
|
||||
return new MirrorOfLifeTrapping(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum MirrorOfLifeTrappingCastPredicate implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
int zcc = input.getZoneChangeCounter(game);
|
||||
Spell spell = game.getStack().getSpell(input.getId());
|
||||
return (spell != null && spell.getZoneChangeCounter(game) == zcc - 1)
|
||||
|| game.getLastKnownInformation(input.getId(), Zone.STACK, zcc - 1) != null;
|
||||
}
|
||||
}
|
||||
|
||||
class MirrorOfLifeTrappingEffect extends OneShotEffect {
|
||||
|
||||
MirrorOfLifeTrappingEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "exile it, then return all other permanent cards exiled with {this} to the battlefield under their owners' control";
|
||||
}
|
||||
|
||||
private MirrorOfLifeTrappingEffect(final MirrorOfLifeTrappingEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MirrorOfLifeTrappingEffect copy() {
|
||||
return new MirrorOfLifeTrappingEffect(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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
ExileZone exileZone = game.getExile().getExileZone(exileZoneId);
|
||||
|
||||
Cards toBattlefield = null;
|
||||
if (exileZone != null && !exileZone.isEmpty()) {
|
||||
toBattlefield = new CardsImpl(exileZone);
|
||||
}
|
||||
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
controller.moveCardsToExile(permanent, source, game, true, exileZoneId, sourceObject.getIdName());
|
||||
}
|
||||
|
||||
if (toBattlefield != null) {
|
||||
game.processAction();
|
||||
controller.moveCards(toBattlefield.getCards(StaticFilters.FILTER_CARD_PERMANENT, game),
|
||||
Zone.BATTLEFIELD, source, game, false, true, true, null);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.condition.common.KickedCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.keyword.KickerAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -32,15 +33,15 @@ public final class OrimsThunder extends CardImpl {
|
|||
this.addAbility(new KickerAbility("{R}"));
|
||||
|
||||
// Destroy target artifact or enchantment. If Orim's Thunder was kicked, it deals damage equal to that permanent's converted mana cost to target creature.
|
||||
this.getSpellAbility().addEffect(new OrimsThunderEffect());
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new OrimsThunderEffect2(),
|
||||
new OrimsThunderDamageEffect(),
|
||||
KickedCondition.ONCE,
|
||||
"If this spell was kicked, it deals damage equal to that permanent's mana value to target creature")
|
||||
);
|
||||
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(KickedCondition.ONCE,
|
||||
new TargetCreaturePermanent()));
|
||||
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(
|
||||
KickedCondition.ONCE, true, new TargetCreaturePermanent()));
|
||||
}
|
||||
|
||||
private OrimsThunder(final OrimsThunder card) {
|
||||
|
|
@ -53,13 +54,13 @@ public final class OrimsThunder extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class OrimsThunderEffect2 extends OneShotEffect {
|
||||
class OrimsThunderDamageEffect extends OneShotEffect {
|
||||
|
||||
OrimsThunderEffect2() {
|
||||
OrimsThunderDamageEffect() {
|
||||
super(Outcome.Damage);
|
||||
}
|
||||
|
||||
private OrimsThunderEffect2(final OrimsThunderEffect2 effect) {
|
||||
private OrimsThunderDamageEffect(final OrimsThunderDamageEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
|
@ -80,33 +81,7 @@ class OrimsThunderEffect2 extends OneShotEffect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public OrimsThunderEffect2 copy() {
|
||||
return new OrimsThunderEffect2(this);
|
||||
public OrimsThunderDamageEffect copy() {
|
||||
return new OrimsThunderDamageEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class OrimsThunderEffect extends OneShotEffect {
|
||||
|
||||
OrimsThunderEffect() {
|
||||
super(Outcome.DestroyPermanent);
|
||||
staticText = "Destroy target artifact or enchantment";
|
||||
}
|
||||
|
||||
private OrimsThunderEffect(final OrimsThunderEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent target = game.getPermanent(source.getFirstTarget());
|
||||
if (target != null) {
|
||||
return target.destroy(source, game, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrimsThunderEffect copy() {
|
||||
return new OrimsThunderEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.p;
|
||||
|
||||
import mage.MageInt;
|
||||
|
|
@ -6,29 +5,18 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.IsStepCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.combat.ReselectDefenderAttackedByTargetEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterAttackingCreature;
|
||||
import mage.game.Game;
|
||||
import mage.game.combat.CombatGroup;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.common.TargetDefender;
|
||||
import mage.target.common.TargetAttackingCreature;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class PortalMage extends CardImpl {
|
||||
|
|
@ -46,11 +34,11 @@ public final class PortalMage extends CardImpl {
|
|||
|
||||
// When Portal Mage enters the battlefield during the declare attackers step, you may reselect which player or planeswalker target attacking creature is attacking.
|
||||
Ability ability = new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new PortalMageEffect(), true),
|
||||
new EntersBattlefieldTriggeredAbility(new ReselectDefenderAttackedByTargetEffect(true), true),
|
||||
new IsStepCondition(PhaseStep.DECLARE_ATTACKERS, false),
|
||||
"When {this} enters during the declare attackers step, you may reselect which player or planeswalker target attacking creature is attacking. "
|
||||
+ "<i>(It can't attack its controller or its controller's planeswalkers.)</i>");
|
||||
ability.addTarget(new TargetCreaturePermanent(new FilterAttackingCreature()));
|
||||
"When {this} enters during the declare attackers step, you may reselect which player or permanent target attacking creature is attacking. "
|
||||
+ "<i>(It can't attack its controller or their permanents)</i>");
|
||||
ability.addTarget(new TargetAttackingCreature());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -63,73 +51,3 @@ public final class PortalMage extends CardImpl {
|
|||
return new PortalMage(this);
|
||||
}
|
||||
}
|
||||
|
||||
class PortalMageEffect extends OneShotEffect {
|
||||
|
||||
PortalMageEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "you may reselect which player or planeswalker target attacking creature is attacking";
|
||||
}
|
||||
|
||||
private PortalMageEffect(final PortalMageEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortalMageEffect copy() {
|
||||
return new PortalMageEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent attackingCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (attackingCreature != null) {
|
||||
CombatGroup combatGroupTarget = null;
|
||||
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||
if (combatGroup.getAttackers().contains(attackingCreature.getId())) {
|
||||
combatGroupTarget = combatGroup;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (combatGroupTarget == null) {
|
||||
return false;
|
||||
}
|
||||
// Reselecting which player or planeswalker a creature is attacking ignores all requirements,
|
||||
// restrictions, and costs associated with attacking.
|
||||
|
||||
// Update possible defender
|
||||
Set<UUID> defenders = new LinkedHashSet<>();
|
||||
for (UUID playerId : game.getCombat().getAttackablePlayers(game)) {
|
||||
defenders.add(playerId);
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_PLANESWALKER, playerId, game)) {
|
||||
defenders.add(permanent.getId());
|
||||
}
|
||||
}
|
||||
// Select the new defender
|
||||
TargetDefender target = new TargetDefender(defenders);
|
||||
if (controller.chooseTarget(Outcome.Damage, target, source, game)) {
|
||||
if (combatGroupTarget.getDefenderId() != null && !combatGroupTarget.getDefenderId().equals(target.getFirstTarget())) {
|
||||
if (combatGroupTarget.changeDefenderPostDeclaration(target.getFirstTarget(), game)) {
|
||||
String attacked = "";
|
||||
Player player = game.getPlayer(target.getFirstTarget());
|
||||
if (player != null) {
|
||||
attacked = player.getLogName();
|
||||
} else {
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
attacked = permanent.getLogName();
|
||||
}
|
||||
}
|
||||
game.informPlayers(attackingCreature.getLogName() + " now attacks " + attacked);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,15 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.filter.predicate.permanent.BlockedThisTurnPredicate;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.BlockedThisTurnWatcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -27,7 +20,7 @@ public final class SizzlingBarrage extends CardImpl {
|
|||
private static final FilterPermanent filter = new FilterCreaturePermanent("creature that blocked this turn");
|
||||
|
||||
static {
|
||||
filter.add(SizzlingBarragePredicate.instance);
|
||||
filter.add(BlockedThisTurnPredicate.instance);
|
||||
}
|
||||
|
||||
public SizzlingBarrage(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
|
@ -36,7 +29,7 @@ public final class SizzlingBarrage extends CardImpl {
|
|||
// Sizzling Barrage deals 4 damage to target creature that blocked this turn.
|
||||
this.getSpellAbility().addEffect(new DamageTargetEffect(4));
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
||||
this.getSpellAbility().addWatcher(new SizzlingBarrageWatcher());
|
||||
this.getSpellAbility().addWatcher(new BlockedThisTurnWatcher());
|
||||
}
|
||||
|
||||
private SizzlingBarrage(final SizzlingBarrage card) {
|
||||
|
|
@ -48,40 +41,3 @@ public final class SizzlingBarrage extends CardImpl {
|
|||
return new SizzlingBarrage(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum SizzlingBarragePredicate implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
SizzlingBarrageWatcher watcher = game.getState().getWatcher(SizzlingBarrageWatcher.class);
|
||||
return watcher != null && watcher.checkCreature(input, game);
|
||||
}
|
||||
}
|
||||
|
||||
class SizzlingBarrageWatcher extends Watcher {
|
||||
|
||||
private final Set<MageObjectReference> blockers = new HashSet<>();
|
||||
|
||||
SizzlingBarrageWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.BLOCKER_DECLARED) {
|
||||
return;
|
||||
}
|
||||
blockers.add(new MageObjectReference(event.getSourceId(), game));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
this.blockers.clear();
|
||||
}
|
||||
|
||||
boolean checkCreature(Permanent permanent, Game game) {
|
||||
return blockers.stream().anyMatch(mor -> mor.refersTo(permanent, game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Hedron Archive", 861, Rarity.UNCOMMON, mage.cards.h.HedronArchive.class));
|
||||
cards.add(new SetCardInfo("Herald's Horn", 862, Rarity.UNCOMMON, mage.cards.h.HeraldsHorn.class));
|
||||
cards.add(new SetCardInfo("Hex", 757, Rarity.RARE, mage.cards.h.Hex.class));
|
||||
cards.add(new SetCardInfo("Hezrou", 131, Rarity.COMMON, mage.cards.h.Hezrou.class));
|
||||
cards.add(new SetCardInfo("High Priest of Penance", 848, Rarity.RARE, mage.cards.h.HighPriestOfPenance.class));
|
||||
cards.add(new SetCardInfo("Highland Forest", 896, Rarity.COMMON, mage.cards.h.HighlandForest.class));
|
||||
cards.add(new SetCardInfo("Hoarding Ogre", 181, Rarity.COMMON, mage.cards.h.HoardingOgre.class));
|
||||
|
|
@ -403,6 +404,7 @@ public final class CommanderLegendsBattleForBaldursGate extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Minsc & Boo, Timeless Heroes", 285, Rarity.MYTHIC, mage.cards.m.MinscBooTimelessHeroes.class));
|
||||
cards.add(new SetCardInfo("Minthara, Merciless Soul", 286, Rarity.UNCOMMON, mage.cards.m.MintharaMercilessSoul.class));
|
||||
cards.add(new SetCardInfo("Mirror Entity", 701, Rarity.RARE, mage.cards.m.MirrorEntity.class));
|
||||
cards.add(new SetCardInfo("Mirror of Life Trapping", 326, Rarity.RARE, mage.cards.m.MirrorOfLifeTrapping.class));
|
||||
cards.add(new SetCardInfo("Mizzium Mortars", 803, Rarity.RARE, mage.cards.m.MizziumMortars.class));
|
||||
cards.add(new SetCardInfo("Mocking Doppelganger", 667, Rarity.RARE, mage.cards.m.MockingDoppelganger.class));
|
||||
cards.add(new SetCardInfo("Modify Memory", 83, Rarity.UNCOMMON, mage.cards.m.ModifyMemory.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
package org.mage.test.cards.single.clb;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
public class HezrouTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String hezrou = "Hezrou"; // 6/6
|
||||
// Whenever one or more creatures you control become blocked, each blocking creature gets -1/-1 until end of turn.
|
||||
private static final String stench = "Demonic Stench"; // {B} Instant
|
||||
// Each creature that blocked this turn gets -1/-1 until end of turn.
|
||||
|
||||
private static final String kraken = "Kraken Hatchling"; // 0/4
|
||||
private static final String guard = "Maritime Guard"; // 1/3
|
||||
private static final String fortress = "Fortress Crab"; // 1/6
|
||||
private static final String turtle = "Aegis Turtle"; // 0/5
|
||||
private static final String pangolin = "Gloom Pangolin"; // 1/5
|
||||
private static final String wishcoin = "Wishcoin Crab"; // 2/5
|
||||
|
||||
private void setupCreatures() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, kraken);
|
||||
addCard(Zone.BATTLEFIELD, playerA, guard);
|
||||
addCard(Zone.BATTLEFIELD, playerA, fortress);
|
||||
addCard(Zone.BATTLEFIELD, playerB, turtle);
|
||||
addCard(Zone.BATTLEFIELD, playerB, pangolin);
|
||||
addCard(Zone.BATTLEFIELD, playerB, wishcoin);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrigger() {
|
||||
setupCreatures();
|
||||
addCard(Zone.BATTLEFIELD, playerA, hezrou);
|
||||
|
||||
attack(1, playerA, kraken, playerB);
|
||||
attack(1, playerA, guard, playerB);
|
||||
attack(1, playerA, fortress, playerB);
|
||||
block(1, playerB, turtle, kraken);
|
||||
block(1, playerB, pangolin, guard);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 19);
|
||||
assertPowerToughness(playerA, kraken, 0, 4);
|
||||
assertPowerToughness(playerA, guard, 1, 3);
|
||||
assertPowerToughness(playerA, fortress, 1, 6);
|
||||
assertPowerToughness(playerB, turtle, -1, 4);
|
||||
assertPowerToughness(playerB, pangolin, 0, 4);
|
||||
assertPowerToughness(playerB, wishcoin, 2, 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdventure() {
|
||||
setupCreatures();
|
||||
addCard(Zone.HAND, playerA, hezrou);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
|
||||
attack(1, playerA, kraken, playerB);
|
||||
attack(1, playerA, guard, playerB);
|
||||
attack(1, playerA, fortress, playerB);
|
||||
block(1, playerB, turtle, kraken);
|
||||
block(1, playerB, pangolin, guard);
|
||||
|
||||
castSpell(1, PhaseStep.END_COMBAT, playerA, stench);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 19);
|
||||
assertPowerToughness(playerA, kraken, 0, 4);
|
||||
assertPowerToughness(playerA, guard, 1, 3);
|
||||
assertPowerToughness(playerA, fortress, 1, 6);
|
||||
assertPowerToughness(playerB, turtle, -1, 4);
|
||||
assertPowerToughness(playerB, pangolin, 0, 4);
|
||||
assertPowerToughness(playerB, wishcoin, 2, 5);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -11,11 +8,9 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.common.AttackedThisTurnWatcher;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* !!!! This effect needs the adding of the watcher in the using card class
|
||||
* <p>
|
||||
* this.getSpellAbility().addWatcher(new AttackedThisTurnWatcher());
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class UntapAllThatAttackedEffect extends OneShotEffect {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package mage.filter.predicate.permanent;
|
||||
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.common.BlockedThisTurnWatcher;
|
||||
|
||||
/**
|
||||
* Requires BlockedThisTurnWatcher to be added to the card
|
||||
*
|
||||
* @author xenohedron
|
||||
*/
|
||||
public enum BlockedThisTurnPredicate implements Predicate<Permanent> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
BlockedThisTurnWatcher watcher = game.getState().getWatcher(BlockedThisTurnWatcher.class);
|
||||
return watcher != null && watcher.checkIfBlocked(input, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "blocked this turn";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.watchers.common;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
|
|
@ -34,12 +33,7 @@ public class BlockedThisTurnWatcher extends Watcher {
|
|||
}
|
||||
|
||||
public boolean checkIfBlocked(Permanent permanent, Game game) {
|
||||
for (MageObjectReference mor : blockedThisTurnCreatures) {
|
||||
if (mor.refersTo(permanent, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return blockedThisTurnCreatures.stream().anyMatch(mor -> mor.refersTo(permanent, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue