From 8556285f0c1da295edd714c238a71a3781b1d1e4 Mon Sep 17 00:00:00 2001 From: L_J Date: Mon, 4 Jun 2018 23:00:44 +0200 Subject: [PATCH] Implemented Gorm the Great --- Mage.Sets/src/mage/cards/g/GormTheGreat.java | 52 +++++++++++++++++++ Mage.Sets/src/mage/sets/Battlebond.java | 1 + .../abilities/effects/RequirementEffect.java | 4 ++ ...MustBeBlockedByAtLeastOneSourceEffect.java | 13 +++++ .../main/java/mage/game/combat/Combat.java | 11 +++- 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/g/GormTheGreat.java diff --git a/Mage.Sets/src/mage/cards/g/GormTheGreat.java b/Mage.Sets/src/mage/cards/g/GormTheGreat.java new file mode 100644 index 00000000000..7678dad9dba --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GormTheGreat.java @@ -0,0 +1,52 @@ + +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.abilities.keyword.PartnerWithAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author L_J + */ +public final class GormTheGreat extends CardImpl { + + public GormTheGreat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.GIANT); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(7); + + // Partner with Virtus the Veiled (When this creature enters the battlefield, target player may put Virtus into their hand from their library, then shuffle.) + this.addAbility(new PartnerWithAbility("Virtus the Veiled", true)); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Gorm the Great must be blocked if able, and Gorm must be blocked by two or more creatures if able. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MustBeBlockedByAtLeastOneSourceEffect(Duration.WhileOnBattlefield, 2) + .setText("{this} must be blocked if able, and {this} must be blocked by two or more creatures if able"))); + } + + public GormTheGreat(final GormTheGreat card) { + super(card); + } + + @Override + public GormTheGreat copy() { + return new GormTheGreat(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Battlebond.java b/Mage.Sets/src/mage/sets/Battlebond.java index cc83734d192..b485fbb218b 100644 --- a/Mage.Sets/src/mage/sets/Battlebond.java +++ b/Mage.Sets/src/mage/sets/Battlebond.java @@ -115,6 +115,7 @@ public final class Battlebond extends ExpansionSet { cards.add(new SetCardInfo("Giant Growth", 200, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); cards.add(new SetCardInfo("Goblin Razerunners", 179, Rarity.RARE, mage.cards.g.GoblinRazerunners.class)); cards.add(new SetCardInfo("Gold-Forged Sentinel", 236, Rarity.UNCOMMON, mage.cards.g.GoldForgedSentinel.class)); + cards.add(new SetCardInfo("Gorm the Great", 8, Rarity.RARE, mage.cards.g.GormTheGreat.class)); cards.add(new SetCardInfo("Greater Good", 201, Rarity.RARE, mage.cards.g.GreaterGood.class)); cards.add(new SetCardInfo("Grotesque Mutation", 145, Rarity.COMMON, mage.cards.g.GrotesqueMutation.class)); cards.add(new SetCardInfo("Grothama, All-Devouring", 71, Rarity.MYTHIC, mage.cards.g.GrothamaAllDevouring.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java b/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java index 5d3fa062c82..a0ea8297392 100644 --- a/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/RequirementEffect.java @@ -76,6 +76,10 @@ public abstract class RequirementEffect extends ContinuousEffectImpl { return null; } + public int getMinNumberOfBlockers() { + return 0; + } + /** * Player related check The player returned or controlled planeswalker must * be attacked with at least one attacker diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java index f07636b3b5c..7375856341d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAtLeastOneSourceEffect.java @@ -35,18 +35,26 @@ import mage.game.permanent.Permanent; * @author LevelX2 */ public class MustBeBlockedByAtLeastOneSourceEffect extends RequirementEffect { + + private int minNumberOfBlockers; public MustBeBlockedByAtLeastOneSourceEffect() { this(Duration.EndOfTurn); } public MustBeBlockedByAtLeastOneSourceEffect(Duration duration) { + this(duration, 1); + } + + public MustBeBlockedByAtLeastOneSourceEffect(Duration duration, int minNumberOfBlockers) { super(duration); + this.minNumberOfBlockers = minNumberOfBlockers; staticText = "{this} must be blocked " + (duration == Duration.EndOfTurn ? "this turn " : "") + "if able"; } public MustBeBlockedByAtLeastOneSourceEffect(final MustBeBlockedByAtLeastOneSourceEffect effect) { super(effect); + this.minNumberOfBlockers = effect.minNumberOfBlockers; } @Override @@ -69,6 +77,11 @@ public class MustBeBlockedByAtLeastOneSourceEffect extends RequirementEffect { return source.getSourceId(); } + @Override + public int getMinNumberOfBlockers() { + return minNumberOfBlockers; + } + @Override public MustBeBlockedByAtLeastOneSourceEffect copy() { return new MustBeBlockedByAtLeastOneSourceEffect(this); diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index c6478382bee..bdc10db7f10 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -695,6 +695,7 @@ public class Combat implements Serializable, Copyable { //20101001 - 509.1c // map with attackers (UUID) that must be blocked by at least one blocker and a set of all creatures that can block it and don't block yet Map> mustBeBlockedByAtLeastOne = new HashMap<>(); + int minNumberOfBlockers = 0; // check mustBlock requirements of creatures from opponents of attacking player for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED, player.getId(), game)) { @@ -710,6 +711,7 @@ public class Combat implements Serializable, Copyable { for (Ability ability : entry.getValue()) { UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game); if (toBeBlockedCreature != null) { + minNumberOfBlockers = effect.getMinNumberOfBlockers(); Set potentialBlockers; if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) { potentialBlockers = mustBeBlockedByAtLeastOne.get(toBeBlockedCreature); @@ -804,6 +806,7 @@ public class Combat implements Serializable, Copyable { for (Ability ability : entry.getValue()) { UUID toBeBlockedCreature = effect.mustBlockAttackerIfElseUnblocked(ability, game); if (toBeBlockedCreature != null) { + minNumberOfBlockers = effect.getMinNumberOfBlockers(); Set potentialBlockers; if (mustBeBlockedByAtLeastOne.containsKey(toBeBlockedCreature)) { potentialBlockers = mustBeBlockedByAtLeastOne.get(toBeBlockedCreature); @@ -898,6 +901,7 @@ public class Combat implements Serializable, Copyable { break; } } + requirementFulfilled &= (combatGroup.getBlockers().size() >= Math.min(minNumberOfBlockers, mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId).size())); if (!requirementFulfilled) { // creature is not blocked but has possible blockers if (controller.isHuman()) { @@ -906,6 +910,9 @@ public class Combat implements Serializable, Copyable { // check if all possible blocker block other creatures they are forced to block // read through all possible blockers for (UUID possibleBlockerId : mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId)) { + if (combatGroup.getBlockers().contains(possibleBlockerId)) { + continue; + } String blockRequiredMessage = isCreatureDoingARequiredBlock( possibleBlockerId, toBeBlockedCreatureId, mustBeBlockedByAtLeastOne, game); if (blockRequiredMessage != null) { // message means not required @@ -931,7 +938,9 @@ public class Combat implements Serializable, Copyable { } defender.declareBlocker(defender.getId(), possibleBlockerId, toBeBlockedCreatureId, game); } - break; + if (combatGroup.getBlockers().size() >= minNumberOfBlockers) { + break; + } } } }