Simplyfy Cloak and Manifest Effects (#4652)

This commit is contained in:
Hans Mackowiak
2024-02-10 05:34:56 +01:00
committed by GitHub
parent 662bc34a31
commit 9257846c39
6 changed files with 278 additions and 353 deletions

View File

@@ -2,69 +2,25 @@ package forge.game.ability.effects;
import java.util.Map;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardZoneTable;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.Localizer;
public class CloakEffect extends SpellAbilityEffect {
public class CloakEffect extends ManifestBaseEffect {
@Override
public void resolve(SpellAbility sa) {
protected String getDefaultMessage() {
return Localizer.getInstance().getMessage("lblChooseCards");
}
@Override
protected Card internalEffect(Card c, Player p, SpellAbility sa, Map<AbilityKey, Object> moveParams) {
final Card source = sa.getHostCard();
final Player activator = sa.getActivatingPlayer();
final Game game = source.getGame();
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(source,
sa.getParam("Amount"), sa) : 1;
CardZoneTable triggerList = new CardZoneTable(game.copyLastStateBattlefield(), game.copyLastStateGraveyard());
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, triggerList.getLastStateBattlefield());
moveParams.put(AbilityKey.LastStateGraveyard, triggerList.getLastStateGraveyard());
moveParams.put(AbilityKey.InternalTriggerTable, triggerList);
for (final Player p : getTargetPlayers(sa, "DefinedPlayer")) {
CardCollection tgtCards;
if (sa.hasParam("Choices") || sa.hasParam("ChoiceZone")) {
ZoneType choiceZone = ZoneType.Hand;
if (sa.hasParam("ChoiceZone")) {
choiceZone = ZoneType.smartValueOf(sa.getParam("ChoiceZone"));
}
CardCollectionView choices = game.getCardsIn(choiceZone);
if (sa.hasParam("Choices")) {
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, source, sa);
}
if (choices.isEmpty()) {
continue;
}
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChooseCards") + " ";
tgtCards = new CardCollection(activator.getController().chooseCardsForEffect(choices, sa, title, amount, amount, false, null));
} else {
tgtCards = getTargetCards(sa);
}
if (sa.hasParam("Shuffle")) {
CardLists.shuffle(tgtCards);
}
for (Card c : tgtCards) {
Card rem = c.cloak(p, sa, moveParams);
if (rem != null && sa.hasParam("RememberCloaked") && rem.isCloaked()) {
source.addRemembered(rem);
}
}
Card rem = c.cloak(p, sa, moveParams);
if (rem != null && sa.hasParam("RememberCloaked") && rem.isCloaked()) {
source.addRemembered(rem);
}
triggerList.triggerChangesZoneAll(game, sa);
return rem;
}
}

View File

@@ -0,0 +1,97 @@
package forge.game.ability.effects;
import java.util.Map;
import com.google.common.collect.Iterables;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardZoneTable;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public abstract class ManifestBaseEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Card source = sa.getHostCard();
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;
for (final Player p : getTargetPlayers(sa, "DefinedPlayer")) {
CardCollection tgtCards;
boolean fromLibrary = false;
if (sa.hasParam("Choices") || sa.hasParam("ChoiceZone")) {
ZoneType choiceZone = ZoneType.Hand;
if (sa.hasParam("ChoiceZone")) {
choiceZone = ZoneType.smartValueOf(sa.getParam("ChoiceZone"));
fromLibrary = choiceZone.equals(ZoneType.Library);
}
CardCollectionView choices = game.getCardsIn(choiceZone);
if (sa.hasParam("Choices")) {
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, source, sa);
}
if (choices.isEmpty()) {
continue;
}
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : getDefaultMessage() + " ";
tgtCards = new CardCollection(activator.getController().chooseCardsForEffect(choices, sa, title, amount, amount, false, null));
} else if ("TopOfLibrary".equals(sa.getParamOrDefault("Defined", "TopOfLibrary"))) {
tgtCards = p.getTopXCardsFromLibrary(amount);
fromLibrary = true;
} else {
tgtCards = getTargetCards(sa);
if (Iterables.all(tgtCards, CardPredicates.inZone(ZoneType.Library))) {
fromLibrary = true;
}
}
if (sa.hasParam("Shuffle")) {
CardLists.shuffle(tgtCards);
}
if (fromLibrary) {
for (Card c : tgtCards) {
// CR 701.34d If an effect instructs a player to manifest multiple cards from their library, those cards are manifested one at a time.
CardZoneTable triggerList = new CardZoneTable(game.copyLastStateBattlefield(), game.copyLastStateGraveyard());
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, triggerList.getLastStateBattlefield());
moveParams.put(AbilityKey.LastStateGraveyard, triggerList.getLastStateGraveyard());
moveParams.put(AbilityKey.InternalTriggerTable, triggerList);
internalEffect(c, p, sa, moveParams);
triggerList.triggerChangesZoneAll(game, sa);
}
} else {
// manifest from other zones should be done at the same time
CardZoneTable triggerList = new CardZoneTable(game.copyLastStateBattlefield(), game.copyLastStateGraveyard());
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, triggerList.getLastStateBattlefield());
moveParams.put(AbilityKey.LastStateGraveyard, triggerList.getLastStateGraveyard());
moveParams.put(AbilityKey.InternalTriggerTable, triggerList);
for (Card c : tgtCards) {
internalEffect(c, p, sa, moveParams);
}
triggerList.triggerChangesZoneAll(game, sa);
}
}
}
abstract protected String getDefaultMessage();
abstract protected Card internalEffect(Card c, Player p, SpellAbility sa, Map<AbilityKey, Object> moveParams);
}

View File

@@ -2,101 +2,23 @@ package forge.game.ability.effects;
import java.util.Map;
import com.google.common.collect.Iterables;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardZoneTable;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.Localizer;
public class ManifestEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
public class ManifestEffect extends ManifestBaseEffect {
protected String getDefaultMessage() {
return Localizer.getInstance().getMessage("lblChooseCardToManifest");
}
protected Card internalEffect(Card c, Player p, SpellAbility sa, Map<AbilityKey, Object> moveParams) {
final Card source = sa.getHostCard();
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;
// Most commonly "defined" is Top of Library
final String defined = sa.getParamOrDefault("Defined", "TopOfLibrary");
for (final Player p : getTargetPlayers(sa, "DefinedPlayer")) {
CardCollection tgtCards;
boolean fromLibrary = false;
if (sa.hasParam("Choices") || sa.hasParam("ChoiceZone")) {
ZoneType choiceZone = ZoneType.Hand;
if (sa.hasParam("ChoiceZone")) {
choiceZone = ZoneType.smartValueOf(sa.getParam("ChoiceZone"));
fromLibrary = choiceZone.equals(ZoneType.Library);
}
CardCollectionView choices = game.getCardsIn(choiceZone);
if (sa.hasParam("Choices")) {
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, source, sa);
}
if (choices.isEmpty()) {
continue;
}
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : Localizer.getInstance().getMessage("lblChooseCardToManifest") + " ";
tgtCards = new CardCollection(activator.getController().chooseCardsForEffect(choices, sa, title, amount, amount, false, null));
} else if ("TopOfLibrary".equals(defined)) {
tgtCards = p.getTopXCardsFromLibrary(amount);
fromLibrary = true;
} else {
tgtCards = getTargetCards(sa);
if (Iterables.all(tgtCards, CardPredicates.inZone(ZoneType.Library))) {
fromLibrary = true;
}
}
if (sa.hasParam("Shuffle")) {
CardLists.shuffle(tgtCards);
}
if (fromLibrary) {
for (Card c : tgtCards) {
// CR 701.34d If an effect instructs a player to manifest multiple cards from their library, those cards are manifested one at a time.
CardZoneTable triggerList = new CardZoneTable(game.copyLastStateBattlefield(), game.copyLastStateGraveyard());
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, triggerList.getLastStateBattlefield());
moveParams.put(AbilityKey.LastStateGraveyard, triggerList.getLastStateGraveyard());
moveParams.put(AbilityKey.InternalTriggerTable, triggerList);
Card rem = c.manifest(p, sa, moveParams);
if (rem != null && sa.hasParam("RememberManifested") && rem.isManifested()) {
source.addRemembered(rem);
}
triggerList.triggerChangesZoneAll(game, sa);
}
} else {
// manifest from other zones should be done at the same time
CardZoneTable triggerList = new CardZoneTable(game.copyLastStateBattlefield(), game.copyLastStateGraveyard());
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, triggerList.getLastStateBattlefield());
moveParams.put(AbilityKey.LastStateGraveyard, triggerList.getLastStateGraveyard());
moveParams.put(AbilityKey.InternalTriggerTable, triggerList);
for (Card c : tgtCards) {
Card rem = c.manifest(p, sa, moveParams);
if (rem != null && sa.hasParam("RememberManifested") && rem.isManifested()) {
source.addRemembered(rem);
}
}
triggerList.triggerChangesZoneAll(game, sa);
}
Card rem = c.manifest(p, sa, moveParams);
if (rem != null && sa.hasParam("RememberManifested") && rem.isManifested()) {
source.addRemembered(rem);
}
return rem;
}
}