diff --git a/Mage.Sets/src/mage/cards/e/EzurisPredation.java b/Mage.Sets/src/mage/cards/e/EzurisPredation.java index ef1c18b4c17..12f004e6fa5 100644 --- a/Mage.Sets/src/mage/cards/e/EzurisPredation.java +++ b/Mage.Sets/src/mage/cards/e/EzurisPredation.java @@ -1,8 +1,7 @@ package mage.cards.e; -import java.util.List; -import java.util.UUID; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; @@ -13,18 +12,23 @@ import mage.constants.Outcome; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.BeastToken2; import mage.players.Player; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class EzurisPredation extends CardImpl { public EzurisPredation(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{G}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{G}{G}{G}"); // For each creature your opponents control, create a 4/4 green Beast creature token. Each of those Beasts fights a different one of those creatures. this.getSpellAbility().addEffect(new EzurisPredationEffect()); @@ -75,6 +79,7 @@ class EzurisPredationEffect extends OneShotEffect { FilterCreaturePermanent filterCreature = new FilterCreaturePermanent(); filterCreature.add(TargetController.OPPONENT.getControllerPredicate()); List creaturesOfOpponents = game.getBattlefield().getActivePermanents(filterCreature, source.getControllerId(), source.getSourceId(), game); + Set morSet = new HashSet<>(); if (!creaturesOfOpponents.isEmpty()) { CreateTokenEffect effect = new CreateTokenEffect(new BeastToken2(), creaturesOfOpponents.size()); effect.apply(game, source); @@ -86,10 +91,15 @@ class EzurisPredationEffect extends OneShotEffect { } Permanent opponentCreature = creaturesOfOpponents.iterator().next(); creaturesOfOpponents.remove(opponentCreature); - token.fight(opponentCreature, source, game); + token.fight(opponentCreature, source, game, false); + morSet.add(new MageObjectReference(token, game)); + morSet.add(new MageObjectReference(opponentCreature, game)); game.informPlayers(token.getLogName() + " fights " + opponentCreature.getLogName()); } } + String data = UUID.randomUUID().toString(); + game.getState().setValue("batchFight_" + data, morSet); + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BATCH_FIGHT, getId(), getId(), source.getControllerId(), data, 0)); } return true; } diff --git a/Mage.Sets/src/mage/cards/n/NeyithOfTheDireHunt.java b/Mage.Sets/src/mage/cards/n/NeyithOfTheDireHunt.java new file mode 100644 index 00000000000..fe1c2f89332 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NeyithOfTheDireHunt.java @@ -0,0 +1,148 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NeyithOfTheDireHunt extends CardImpl { + + public NeyithOfTheDireHunt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever one or more creatures you control fight or become blocked, draw a card. + this.addAbility(new NeyithOfTheDireHuntTriggeredAbility()); + + // At the beginning of combat on your turn, you may pay {2}{R/G}. If you do, double target creature's power until end of turn. That creature must be blocked this combat if able. + Ability ability = new BeginningOfCombatTriggeredAbility(new DoIfCostPaid( + new NeyithOfTheDireHuntEffect(), new ManaCostsImpl<>("{2}{R/G}") + ), TargetController.YOU, false); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private NeyithOfTheDireHunt(final NeyithOfTheDireHunt card) { + super(card); + } + + @Override + public NeyithOfTheDireHunt copy() { + return new NeyithOfTheDireHunt(this); + } +} + +// TODO: this needs to work with cards like Choking Vines +class NeyithOfTheDireHuntTriggeredAbility extends TriggeredAbilityImpl { + + NeyithOfTheDireHuntTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1)); + } + + private NeyithOfTheDireHuntTriggeredAbility(final NeyithOfTheDireHuntTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.BATCH_FIGHT + || event.getType() == GameEvent.EventType.DECLARED_BLOCKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + switch (event.getType()) { + case BATCH_FIGHT: + Object value = game.getState().getValue("batchFight_" + event.getData()); + if (!(value instanceof Set)) { + return false; + } + Set permanents = (Set) value; + return permanents + .stream() + .map(mor -> mor.getPermanentOrLKIBattlefield(game)) + .filter(Objects::nonNull) + .map(Controllable::getControllerId) + .anyMatch(this.getControllerId()::equals); + case DECLARED_BLOCKERS: + return game.getCombat() + .getBlockingGroups() + .stream() + .map(CombatGroup::getAttackers) + .flatMap(Collection::stream) + .map(game::getControllerId) + .anyMatch(this.getControllerId()::equals); + default: + return false; + } + } + + @Override + public NeyithOfTheDireHuntTriggeredAbility copy() { + return new NeyithOfTheDireHuntTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever one or more creatures you control fight or become blocked, draw a card."; + } +} + +class NeyithOfTheDireHuntEffect extends OneShotEffect { + + NeyithOfTheDireHuntEffect() { + super(Outcome.Benefit); + staticText = "double target creature's power until end of turn. " + + "That creature must be blocked this combat if able"; + } + + private NeyithOfTheDireHuntEffect(final NeyithOfTheDireHuntEffect effect) { + super(effect); + } + + @Override + public NeyithOfTheDireHuntEffect copy() { + return new NeyithOfTheDireHuntEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } + int power = permanent.getPower().getValue(); + game.addEffect(new BoostTargetEffect(power, power, Duration.EndOfTurn), source); + game.addEffect(new MustBeBlockedByAtLeastOneTargetEffect(Duration.EndOfCombat), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/Jumpstart.java b/Mage.Sets/src/mage/sets/Jumpstart.java index 123c86c98a6..3a6af4c9cf8 100644 --- a/Mage.Sets/src/mage/sets/Jumpstart.java +++ b/Mage.Sets/src/mage/sets/Jumpstart.java @@ -323,6 +323,7 @@ public final class Jumpstart extends ExpansionSet { cards.add(new SetCardInfo("Nebelgast Herald", 160, Rarity.UNCOMMON, mage.cards.n.NebelgastHerald.class)); cards.add(new SetCardInfo("Nessian Hornbeetle", 413, Rarity.UNCOMMON, mage.cards.n.NessianHornbeetle.class)); cards.add(new SetCardInfo("New Horizons", 414, Rarity.COMMON, mage.cards.n.NewHorizons.class)); + cards.add(new SetCardInfo("Neyith of the Dire Hunt", 30, Rarity.RARE, mage.cards.n.NeyithOfTheDireHunt.class)); cards.add(new SetCardInfo("Nightshade Stinger", 258, Rarity.COMMON, mage.cards.n.NightshadeStinger.class)); cards.add(new SetCardInfo("Nocturnal Feeder", 16, Rarity.COMMON, mage.cards.n.NocturnalFeeder.class)); cards.add(new SetCardInfo("Nyxathid", 259, Rarity.RARE, mage.cards.n.Nyxathid.class)); diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index b7d352af3c3..a3712958e12 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -308,6 +308,7 @@ public class GameEvent implements Serializable { DESTROYED_PERMANENT, SACRIFICE_PERMANENT, SACRIFICED_PERMANENT, FIGHTED_PERMANENT, + BATCH_FIGHT, EXPLOITED_CREATURE, EVOLVED_CREATURE, EMBALMED_CREATURE, diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index f9612d19258..526c7ea8ba3 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -152,6 +152,8 @@ public interface Permanent extends Card, Controllable { boolean fight(Permanent fightTarget, Ability source, Game game); + boolean fight(Permanent fightTarget, Ability source, Game game,boolean batchTrigger); + boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent); String getValue(GameState state); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 44b02614901..f662ab7332b 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -1559,10 +1559,24 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public boolean fight(Permanent fightTarget, Ability source, Game game) { + return this.fight(fightTarget, source, game, true); + } + + @Override + public boolean fight(Permanent fightTarget, Ability source, Game game, boolean batchTrigger) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, fightTarget.getId(), getId(), source.getControllerId())); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, getId(), fightTarget.getId(), source.getControllerId())); - damage(fightTarget.getPower().getValue(), fightTarget.getId(), game, false, true); + damage(fightTarget.getPower().getValue(), fightTarget.getId(), game); fightTarget.damage(getPower().getValue(), getId(), game); + if (!batchTrigger) { + return true; + } + Set morSet = new HashSet<>(); + morSet.add(new MageObjectReference(this, game)); + morSet.add(new MageObjectReference(fightTarget, game)); + String data = UUID.randomUUID().toString(); + game.getState().setValue("batchFight_" + data, morSet); + game.fireEvent(GameEvent.getEvent(EventType.BATCH_FIGHT, getId(), getId(), source.getControllerId(), data, 0)); return true; }