[LTC] Implement Elrond of the White Council (#10731)

This commit is contained in:
Susucre 2023-08-03 06:26:19 +02:00 committed by GitHub
parent 3cb22932a0
commit 23781ecb37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 194 additions and 2 deletions

View file

@ -0,0 +1,186 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.TwoChoiceVote;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.targetpointer.FixedTargets;
import mage.target.targetpointer.TargetPointer;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author Susucr
*/
public final class ElrondOfTheWhiteCouncil extends CardImpl {
public ElrondOfTheWhiteCouncil(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{U}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.NOBLE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Secret council -- When Elrond of the White Council enters the battlefield, each player secretly votes for fellowship or aid, then those votes are revealed. For each fellowship vote, the voter chooses a creature they control. You gain control of each creature chosen this way, and they gain "This creature can't attack its owner." Then for each aid vote, put a +1/+1 counter on each creature you control.
this.addAbility(new EntersBattlefieldTriggeredAbility(
new ElrondOfWhiteCouncilEffect()
).setAbilityWord(AbilityWord.SECRET_COUNCIL));
}
private ElrondOfTheWhiteCouncil(final ElrondOfTheWhiteCouncil card) {
super(card);
}
@Override
public ElrondOfTheWhiteCouncil copy() {
return new ElrondOfTheWhiteCouncil(this);
}
}
class ElrondOfWhiteCouncilEffect extends OneShotEffect {
ElrondOfWhiteCouncilEffect() {
super(Outcome.Benefit);
staticText = "each player secretly votes for fellowship or aid, then those votes are revealed. "
+ "For each fellowship vote, the voter chooses a creature they control. You gain control "
+ "of each creature chosen this way, and they gain \"This creature can't attack its owner.\" "
+ "Then for each aid vote, put a +1/+1 counter on each creature you control.";
}
private ElrondOfWhiteCouncilEffect(final ElrondOfWhiteCouncilEffect effect) {
super(effect);
}
@Override
public ElrondOfWhiteCouncilEffect copy() {
return new ElrondOfWhiteCouncilEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
TwoChoiceVote vote = new TwoChoiceVote(
"Fellowship",
"Aid",
Outcome.Benefit,
true
);
vote.doVotes(source, game);
Set<Permanent> chosenCreatures = new HashSet<>();
// For each fellowship vote,
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
int countFellowship = (int) vote.getVotes(playerId).stream().filter(b -> b).count();
if (countFellowship < 1) {
continue;
}
Player player = game.getPlayer(playerId);
if (player == null) {
continue;
}
// Relevant ruling, why this is a loop and the same creature may be chosen multiple time:
// (2023-06-16): If you have multiple votes, you can vote for fellowship multiple times. If you do, you can choose the same creature each time.
for (int i = 0; i < countFellowship; ++i) {
TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(1);
target.setNotTarget(true);
if (player.chooseTarget(Outcome.Detriment, target, source, game)) {
Permanent chosen = game.getPermanent(target.getFirstTarget());
if (chosen == null) {
continue;
}
// other players must know what choice was made before them.
game.informPlayers(player.getLogName() + " has chosen " + chosen.getLogName() + CardUtil.getSourceLogName(game, source));
chosenCreatures.add(chosen);
}
}
}
// You gain control of each creature chosen this way, and they gain "This creature can't attack its owner."
TargetPointer pointer = new FixedTargets(chosenCreatures.stream().collect(Collectors.toList()), game);
game.addEffect(new GainControlTargetEffect(
Duration.WhileOnBattlefield
).setTargetPointer(pointer), source);
game.addEffect(new GainAbilityTargetEffect(
new SimpleStaticAbility(new CantAttackItsOwnerEffect()),
Duration.WhileOnBattlefield
).setTargetPointer(pointer), source);
// Need to process the control change.
game.getState().processAction(game);
// Then for each aid vote, put a +1/+1 counter on each creature you control.
int countAid = vote.getVoteCount(false);
if (countAid > 0) {
new AddCountersAllEffect(
CounterType.P1P1.createInstance(countAid),
StaticFilters.FILTER_CONTROLLED_CREATURE
).apply(game, source);
}
return true;
}
}
class CantAttackItsOwnerEffect extends RestrictionEffect {
CantAttackItsOwnerEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
staticText = "This creature can't attack its owner";
}
private CantAttackItsOwnerEffect(final CantAttackItsOwnerEffect effect) {
super(effect);
}
@Override
public CantAttackItsOwnerEffect copy() {
return new CantAttackItsOwnerEffect(this);
}
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
return permanent.getId().equals(source.getSourceId());
}
@Override
public boolean canAttack(Permanent attacker, UUID defenderId, Ability source, Game game, boolean canUseChooseDialogs) {
if (defenderId == null || attacker == null) {
return true;
}
return !defenderId.equals(attacker.getOwnerId());
}
}

View file

@ -79,6 +79,7 @@ public final class TalesOfMiddleEarthCommander extends ExpansionSet {
cards.add(new SetCardInfo("Drowned Catacomb", 305, Rarity.RARE, mage.cards.d.DrownedCatacomb.class));
cards.add(new SetCardInfo("Dusk // Dawn", 166, Rarity.RARE, mage.cards.d.DuskDawn.class));
cards.add(new SetCardInfo("Earthquake", 214, Rarity.RARE, mage.cards.e.Earthquake.class));
cards.add(new SetCardInfo("Elrond of the White Council", 51, Rarity.RARE, mage.cards.e.ElrondOfTheWhiteCouncil.class));
cards.add(new SetCardInfo("Elvish Archdruid", 237, Rarity.RARE, mage.cards.e.ElvishArchdruid.class));
cards.add(new SetCardInfo("Elvish Mystic", 238, Rarity.COMMON, mage.cards.e.ElvishMystic.class));
cards.add(new SetCardInfo("Elvish Piper", 239, Rarity.RARE, mage.cards.e.ElvishPiper.class));

View file

@ -17,11 +17,17 @@ public class TwoChoiceVote extends VoteHandler<Boolean> {
private final String choice1;
private final String choice2;
private final Outcome outcome;
private final boolean secret;
public TwoChoiceVote(String choice1, String choice2, Outcome outcome) {
this(choice1, choice2, outcome, false);
}
public TwoChoiceVote(String choice1, String choice2, Outcome outcome, boolean secret) {
this.choice1 = choice1;
this.choice2 = choice2;
this.outcome = outcome;
this.secret = secret;
}
@Override

View file

@ -6,7 +6,6 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.target.TargetPermanent;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class TargetCreaturePermanent extends TargetPermanent {
@ -31,7 +30,7 @@ public class TargetCreaturePermanent extends TargetPermanent {
super(minNumTargets, maxNumTargets, filter, notTarget);
}
public TargetCreaturePermanent(final TargetCreaturePermanent target) {
protected TargetCreaturePermanent(final TargetCreaturePermanent target) {
super(target);
}