Fix ChangeZone* not always shuffling (#4976)

* Support nicknames for non-rebranded

* Fix ChangeZone* not always shuffling
This commit is contained in:
tool4ever
2024-04-07 22:28:23 +02:00
committed by GitHub
parent f664afd4a4
commit a8211c3da3
7 changed files with 40 additions and 30 deletions

View File

@@ -30,6 +30,8 @@ import forge.item.PaperCard;
import forge.util.CollectionSuppliers;
import forge.util.Lang;
import forge.util.TextUtil;
import forge.util.lang.LangEnglish;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
@@ -371,6 +373,11 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
}
private void buildRenamedCards() {
Lang lang = Lang.getInstance();
if (lang == null) {
// for some tests
lang = new LangEnglish();
}
// for now just check Universes Within
for (CardInSet cis : editions.get("SLX").getCards()) {
String orgName = alternateName.get(cis.name);
@@ -382,7 +389,10 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
renamedMain.setName(renamedMain.getAltName());
renamedMain.setAltName(null);
// TODO this could mess up some "named ..." cardname literals but there's no printing like that currently
renamedMain.setOracleText(renamedMain.getOracleText().replace(orgName, renamedMain.getName()));
renamedMain.setOracleText(renamedMain.getOracleText()
.replace(orgName, renamedMain.getName())
.replace(lang.getNickName(orgName), lang.getNickName(renamedMain.getName()))
);
facesByName.put(renamedMain.getName(), renamedMain);
CardFace renamedOther = null;
if (org.getOtherPart() != null) {
@@ -390,7 +400,10 @@ public final class CardDb implements ICardDatabase, IDeckGenPool {
orgName = renamedOther.getName();
renamedOther.setName(renamedOther.getAltName());
renamedOther.setAltName(null);
renamedOther.setOracleText(renamedOther.getOracleText().replace(orgName, renamedOther.getName()));
renamedOther.setOracleText(renamedOther.getOracleText()
.replace(orgName, renamedOther.getName())
.replace(lang.getNickName(orgName), lang.getNickName(renamedOther.getName()))
);
facesByName.put(renamedOther.getName(), renamedOther);
}

View File

@@ -36,12 +36,11 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Card source = sa.getHostCard();
if (!checkValidDuration(sa.getParam("Duration"), sa)) {
return;
}
final Card source = sa.getHostCard();
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
final List<ZoneType> origin = ZoneType.listValueOf(sa.getParam("Origin"));
@@ -239,13 +238,11 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
addUntilCommand(sa, untilHostLeavesPlayCommand(triggerList, sa));
}
// if Shuffle parameter exists, and any amount of cards were owned by
// that player, then shuffle that library
// CR 701.20d If an effect would cause a player to shuffle a set of objects into a library,
// that library is shuffled even if there are no objects in that set.
if (sa.hasParam("Shuffle")) {
for (Player p : game.getPlayers()) {
if (Iterables.any(cards, CardPredicates.isOwner(p))) {
p.shuffle(sa);
}
for (Player p : tgtPlayers) {
p.shuffle(sa);
}
}
}

View File

@@ -450,9 +450,9 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
*/
private void changeKnownOriginResolve(final SpellAbility sa) {
CardCollectionView tgtCards = getTargetCards(sa);
final Player player = sa.getActivatingPlayer();
final Player activator = sa.getActivatingPlayer();
final Card hostCard = sa.getHostCard();
final Game game = player.getGame();
final Game game = activator.getGame();
final CardCollection commandCards = new CardCollection();
ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
@@ -464,7 +464,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
int libraryPosition = sa.hasParam("LibraryPosition") ?
AbilityUtils.calculateAmount(hostCard, sa.getParam("LibraryPosition"), sa) : 0;
if (sa.hasParam("DestinationAlternative")) {
Pair<ZoneType, Integer> pair = handleAltDest(sa, hostCard, destination, libraryPosition, player);
Pair<ZoneType, Integer> pair = handleAltDest(sa, hostCard, destination, libraryPosition, activator);
destination = pair.getKey();
libraryPosition = pair.getValue();
}
@@ -503,7 +503,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
final boolean shuffle = sa.hasParam("Shuffle") && "True".equals(sa.getParam("Shuffle"));
boolean combatChanged = false;
Player chooser = player;
Player chooser = activator;
if (sa.hasParam("Chooser")) {
chooser = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("Chooser"), sa).get(0);
}
@@ -588,11 +588,11 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (sa.hasParam("WithCountersType")) {
CounterType cType = CounterType.getType(sa.getParam("WithCountersType"));
int cAmount = AbilityUtils.calculateAmount(hostCard, sa.getParamOrDefault("WithCountersAmount", "1"), sa);
gameCard.addEtbCounter(cType, cAmount, player);
gameCard.addEtbCounter(cType, cAmount, activator);
}
if (sa.hasParam("GainControl")) {
final String g = sa.getParam("GainControl");
Player newController = g.equals("True") ? player :
Player newController = g.equals("True") ? activator :
AbilityUtils.getDefinedPlayers(hostCard, g, sa).get(0);
if (newController != null) {
if (newController != gameCard.getController()) {
@@ -615,7 +615,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (!list.isEmpty()) {
Map<String, Object> params = Maps.newHashMap();
params.put("Attach", gameCard);
Card attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectACardAttachSourceTo", gameCard.toString()), params);
Card attachedTo = activator.getController().chooseSingleEntityForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectACardAttachSourceTo", gameCard.toString()), params);
// TODO can't attach later or moveToPlay would attach indirectly
// bypass canBeAttached to skip Protection checks when trying to attach multiple auras that would grant protection
@@ -630,7 +630,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (!list.isEmpty()) {
Map<String, Object> params = Maps.newHashMap();
params.put("Attach", gameCard);
Player attachedTo = player.getController().chooseSingleEntityForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectAPlayerAttachSourceTo", gameCard.toString()), params);
Player attachedTo = activator.getController().chooseSingleEntityForEffect(list, sa, Localizer.getInstance().getMessage("lblSelectAPlayerAttachSourceTo", gameCard.toString()), params);
gameCard.attachToEntity(attachedTo, sa);
}
else { // When it should enter the battlefield attached to an illegal player it fails
@@ -715,7 +715,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (ZoneType.Hand.equals(destination) && ZoneType.Command.equals(originZone.getZoneType())) {
StringBuilder sb = new StringBuilder();
sb.append(movedCard.getName()).append(" has moved from Command Zone to ").append(player).append("'s hand.");
sb.append(movedCard.getName()).append(" has moved from Command Zone to ").append(activator).append("'s hand.");
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
commandCards.add(movedCard); //add to list to reveal the commandzone cards
}
@@ -732,7 +732,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (sa.hasParam("WithCountersType")) {
CounterType cType = CounterType.getType(sa.getParam("WithCountersType"));
int cAmount = AbilityUtils.calculateAmount(hostCard, sa.getParamOrDefault("WithCountersAmount", "1"), sa);
movedCard.addCounter(cType, cAmount, player, counterTable);
movedCard.addCounter(cType, cAmount, activator, counterTable);
}
if (sa.hasParam("ExileFaceDown") || sa.hasParam("FaceDown")) {
@@ -744,7 +744,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
movedCard.setForetoldCostByEffect(true);
}
// look at the exiled card
movedCard.addMayLookTemp(player);
movedCard.addMayLookTemp(activator);
}
// CR 400.7k
@@ -759,7 +759,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (sa.hasParam("WithCountersType")) {
CounterType cType = CounterType.getType(sa.getParam("WithCountersType"));
int cAmount = AbilityUtils.calculateAmount(hostCard, sa.getParamOrDefault("WithCountersAmount", "1"), sa);
meld.addCounter(cType, cAmount, player, counterTable);
meld.addCounter(cType, cAmount, activator, counterTable);
}
}
if (gameCard.hasMergedCard()) {
@@ -768,7 +768,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (sa.hasParam("WithCountersType")) {
CounterType cType = CounterType.getType(sa.getParam("WithCountersType"));
int cAmount = AbilityUtils.calculateAmount(hostCard, sa.getParamOrDefault("WithCountersAmount", "1"), sa);
c.addCounter(cType, cAmount, player, counterTable);
c.addCounter(cType, cAmount, activator, counterTable);
}
}
}
@@ -819,7 +819,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
//reveal command cards that changes zone from command zone to player's hand
if (!commandCards.isEmpty()) {
game.getAction().reveal(commandCards, player, true, "Revealed cards in ");
game.getAction().reveal(commandCards, activator, true, "Revealed cards in ");
}
triggerList.triggerChangesZoneAll(game, sa);
@@ -848,8 +848,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
// FCollection already does use set.
pl.add(tgtC.getOwner());
}
if (pl.isEmpty()) {
pl.add(activator);
}
}
for (final Player p : pl) {
p.shuffle(sa);
}

View File

@@ -491,7 +491,6 @@ public class DigEffect extends SpellAbilityEffect {
}
}
}
}
}
}

View File

@@ -25,8 +25,7 @@ public abstract class ManifestBaseEffect extends SpellAbilityEffect {
final Player activator = sa.getActivatingPlayer();
final Game game = source.getGame();
// Usually a number leaving possibility for X, Sacrifice X land: Manifest X creatures.
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(source,
sa.getParam("Amount"), sa) : 1;
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(source, sa.getParam("Amount"), sa) : 1;
for (final Player p : getTargetPlayers(sa, "DefinedPlayer")) {
CardCollection tgtCards;

View File

@@ -4,7 +4,7 @@ Types:Sorcery
A:SP$ Draw | Defined$ Player | Upto$ True | NumCards$ 2 | SubAbility$ DBRepeat | AILogic$ GainLife | SpellDescription$ Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life.
SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBGainLife | StackDescription$ For each card less than two a player draws this way, that player gains 2 life.
SVar:DBGainLife:DB$ GainLife | LifeAmount$ AFNotDrawnNum | Defined$ Player.IsRemembered
SVar:Y:Count$SVar$AFNotDrawnNum/NMinus.2
SVar:Y:SVar$AFNotDrawnNum/NMinus.2
SVar:X:SVar$Y/Twice
AI:RemoveDeck:All
Oracle:Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life.

View File

@@ -4,7 +4,7 @@ Types:Instant
A:SP$ Draw | Defined$ Player | Upto$ True | NumCards$ 2 | SubAbility$ DBRepeat | AILogic$ GainLife | SpellDescription$ Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life.
SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBGainLife | StackDescription$ For each card less than two a player draws this way, that player gains 2 life.
SVar:DBGainLife:DB$ GainLife | LifeAmount$ AFNotDrawnNum | Defined$ Player.IsRemembered
SVar:Y:Count$SVar$AFNotDrawnNum/NMinus.2
SVar:Y:SVar$AFNotDrawnNum/NMinus.2
SVar:X:SVar$Y/Twice
AI:RemoveDeck:All
Oracle:Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life.