mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[40K] Implement Seeker of Slaanesh; added new must attack option (#12712)
* Add player-based "must attack" requirement check * Implement Seeker of Slaanesh and add (ignored) test * Fix check for ability of any controlled creatures to attack * rename misleading variable
This commit is contained in:
parent
060551ab48
commit
4259b7fa39
4 changed files with 120 additions and 1 deletions
|
|
@ -1916,6 +1916,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
// check if enough attackers are declared
|
||||
// check if players have to be attacked
|
||||
Set<UUID> playersToAttackIfAble = new HashSet<>();
|
||||
|
||||
// or if active player must attack with anything
|
||||
boolean mustAttack = false;
|
||||
|
||||
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(null, true, game).entrySet()) {
|
||||
RequirementEffect effect = entry.getKey();
|
||||
for (Ability ability : entry.getValue()) {
|
||||
|
|
@ -1923,6 +1927,9 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (playerToAttack != null) {
|
||||
playersToAttackIfAble.add(playerToAttack);
|
||||
}
|
||||
if (effect.mustAttack(game)){
|
||||
mustAttack = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!playersToAttackIfAble.isEmpty()) {
|
||||
|
|
@ -1960,6 +1967,16 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
}
|
||||
|
||||
if (mustAttack && game.getCombat().getAttackers().isEmpty()){
|
||||
// no attackers, but required to attack with something -- check if anything can attack
|
||||
for (Permanent attacker : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, getId(), game)) {
|
||||
if (attacker.canAttackInPrinciple(null, game)){
|
||||
game.informPlayer(this, "You are forced to attack with at least one creature, e.g. " + attacker.getIdName() + ".");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
83
Mage.Sets/src/mage/cards/s/SeekerOfSlaanesh.java
Normal file
83
Mage.Sets/src/mage/cards/s/SeekerOfSlaanesh.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jimga150
|
||||
*/
|
||||
public final class SeekerOfSlaanesh extends CardImpl {
|
||||
|
||||
public SeekerOfSlaanesh(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||
|
||||
this.subtype.add(SubType.DEMON);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// Allure of Slaanesh -- Each opponent must attack with at least one creature each combat if able.
|
||||
addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SeekerOfSlaaneshForceAttackEffect(Duration.WhileOnBattlefield))
|
||||
.withFlavorWord("Allure of Slaanesh"));
|
||||
}
|
||||
|
||||
private SeekerOfSlaanesh(final SeekerOfSlaanesh card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekerOfSlaanesh copy() {
|
||||
return new SeekerOfSlaanesh(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Based on TroveOfTemptationForceAttackEffect
|
||||
class SeekerOfSlaaneshForceAttackEffect extends RequirementEffect {
|
||||
|
||||
SeekerOfSlaaneshForceAttackEffect(Duration duration) {
|
||||
super(duration, true);
|
||||
staticText = "Each opponent must attack with at least one creature each combat if able.";
|
||||
}
|
||||
|
||||
private SeekerOfSlaaneshForceAttackEffect(final SeekerOfSlaaneshForceAttackEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekerOfSlaaneshForceAttackEffect copy() {
|
||||
return new SeekerOfSlaaneshForceAttackEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustAttack(Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mustBlock(Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
return controller != null && controller.hasOpponent(game.getActivePlayerId(), game);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -224,6 +224,7 @@ public final class Warhammer40000 extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Scoured Barrens", 293, Rarity.COMMON, mage.cards.s.ScouredBarrens.class));
|
||||
cards.add(new SetCardInfo("Screamer-Killer", 84, Rarity.RARE, mage.cards.s.ScreamerKiller.class));
|
||||
cards.add(new SetCardInfo("Sculpting Steel", 247, Rarity.RARE, mage.cards.s.SculptingSteel.class));
|
||||
cards.add(new SetCardInfo("Seeker of Slaanesh", 85, Rarity.UNCOMMON, mage.cards.s.SeekerOfSlaanesh.class));
|
||||
cards.add(new SetCardInfo("Shadow in the Warp", 140, Rarity.RARE, mage.cards.s.ShadowInTheWarp.class));
|
||||
cards.add(new SetCardInfo("Shard of the Nightbringer", 55, Rarity.RARE, mage.cards.s.ShardOfTheNightbringer.class));
|
||||
cards.add(new SetCardInfo("Shard of the Void Dragon", 56, Rarity.RARE, mage.cards.s.ShardOfTheVoidDragon.class));
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ public class AttackAndBlockByAITest extends CardTestPlayerBaseAI {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: need to fix Trove of Temptation effect (player must attack by one creature)
|
||||
@Ignore // TODO: need to fix Trove of Temptation effect (player must be attacked by one creature)
|
||||
public void test_ForceAttack_1_small_vs_1_big_b() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Arbor Elf", 1); // 1/1
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Ancient Brontodon", 1); // 9/9
|
||||
|
|
@ -193,6 +193,24 @@ public class AttackAndBlockByAITest extends CardTestPlayerBaseAI {
|
|||
assertLife(playerB, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: need to fix Seeker of Slaanesh effect (players must attack by one creature)
|
||||
public void test_ForceAttack_any() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Arbor Elf", 1); // 1/1
|
||||
// Each opponent must attack with at least one creature each combat if able.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Seeker of Slaanesh", 1); // 3/3
|
||||
|
||||
block(1, playerB, "Seeker of Slaanesh", "Arbor Elf");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Arbor Elf", 1);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Attack_1_with_counters_vs_1() {
|
||||
// chainbreaker real stats is 1/1, it's can be saftly attacked
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue