master #8

Merged
Failure merged 8 commits from External/mage:master into master 2024-12-10 22:47:57 -08:00
18 changed files with 378 additions and 195 deletions

View file

@ -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

View file

@ -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 &

View file

@ -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 &

View file

@ -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

View file

@ -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();

View file

@ -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)),

View file

@ -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;

View 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);
}
}

View file

@ -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);

View 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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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));
}
}

View file

@ -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));

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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";
}
}

View file

@ -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