mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Merge branch 'war-tricky-cards' into 'master'
Added Ashiok, Dream Render. See merge request core-developers/forge!1644
This commit is contained in:
@@ -316,6 +316,11 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
for (final Player p : pDefined) {
|
for (final Player p : pDefined) {
|
||||||
CardCollectionView list = p.getCardsIn(origin);
|
CardCollectionView list = p.getCardsIn(origin);
|
||||||
|
|
||||||
|
// remove cards that won't be seen if library can't be searched
|
||||||
|
if (!ai.canSearchLibraryWith(sa, p)) {
|
||||||
|
list = CardLists.filter(list, Predicates.not(CardPredicates.inZone(ZoneType.Library)));
|
||||||
|
}
|
||||||
|
|
||||||
if (type != null && p == ai) {
|
if (type != null && p == ai) {
|
||||||
// AI only "knows" about his information
|
// AI only "knows" about his information
|
||||||
list = CardLists.getValidCards(list, type, source.getController(), source);
|
list = CardLists.getValidCards(list, type, source.getController(), source);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import forge.ai.*;
|
import forge.ai.*;
|
||||||
@@ -57,6 +58,11 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
CardCollectionView oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents());
|
CardCollectionView oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents());
|
||||||
CardCollectionView computerType = ai.getCardsIn(origin);
|
CardCollectionView computerType = ai.getCardsIn(origin);
|
||||||
|
|
||||||
|
// remove cards that won't be seen in AI's own library if it can't be searched
|
||||||
|
if (!ai.canSearchLibraryWith(sa, ai)) {
|
||||||
|
computerType = CardLists.filter(computerType, Predicates.not(CardPredicates.inZone(ZoneType.Library)));
|
||||||
|
}
|
||||||
|
|
||||||
// Ugin check need to be done before filterListByType because of ChosenX
|
// Ugin check need to be done before filterListByType because of ChosenX
|
||||||
// Ugin AI: always try to sweep before considering +1
|
// Ugin AI: always try to sweep before considering +1
|
||||||
if (sourceName.equals("Ugin, the Spirit Dragon")) {
|
if (sourceName.equals("Ugin, the Spirit Dragon")) {
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
|
|||||||
cards = new CardCollection();
|
cards = new CardCollection();
|
||||||
for (final Player p : tgtPlayers) {
|
for (final Player p : tgtPlayers) {
|
||||||
cards.addAll(p.getCardsIn(origin));
|
cards.addAll(p.getCardsIn(origin));
|
||||||
|
|
||||||
|
if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && !sa.getActivatingPlayer().canSearchLibraryWith(sa, p)) {
|
||||||
|
cards.removeAll(p.getCardsIn(ZoneType.Library));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (origin.contains(ZoneType.Library) && sa.hasParam("Search")) {
|
if (origin.contains(ZoneType.Library) && sa.hasParam("Search")) {
|
||||||
// Search library using changezoneall effect need a param "Search"
|
// Search library using changezoneall effect need a param "Search"
|
||||||
@@ -58,14 +63,14 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
|
|||||||
cards.addAll(p.getCardsIn(ZoneType.Library, fetchNum));
|
cards.addAll(p.getCardsIn(ZoneType.Library, fetchNum));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sa.getActivatingPlayer().hasKeyword("CantSearchLibrary")) {
|
if (!sa.getActivatingPlayer().canSearchLibraryWith(sa, null)) {
|
||||||
// all these cards have "then that player shuffles", mandatory shuffle
|
// all these cards have "then that player shuffles", mandatory shuffle
|
||||||
cards.removeAll(game.getCardsIn(ZoneType.Library));
|
cards.removeAll(game.getCardsIn(ZoneType.Library));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && !sa.getActivatingPlayer().hasKeyword("CantSearchLibrary")) {
|
if (origin.contains(ZoneType.Library) && sa.hasParam("Search") && sa.getActivatingPlayer().canSearchLibraryWith(sa, null)) {
|
||||||
CardCollection libCards = CardLists.getValidCards(cards, "Card.inZoneLibrary", sa.getActivatingPlayer(), source);
|
CardCollection libCards = CardLists.getValidCards(cards, "Card.inZoneLibrary", sa.getActivatingPlayer(), source);
|
||||||
CardCollection libCardsYouOwn = CardLists.filterControlledBy(libCards, sa.getActivatingPlayer());
|
CardCollection libCardsYouOwn = CardLists.filterControlledBy(libCards, sa.getActivatingPlayer());
|
||||||
if (!libCardsYouOwn.isEmpty()) { // Only searching one's own library would fire Archive Trap's altcost
|
if (!libCardsYouOwn.isEmpty()) { // Only searching one's own library would fire Archive Trap's altcost
|
||||||
|
|||||||
@@ -767,7 +767,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
fetchList.addAll(player.getCardsIn(ZoneType.Library, fetchNum));
|
fetchList.addAll(player.getCardsIn(ZoneType.Library, fetchNum));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (decider.hasKeyword("CantSearchLibrary")) {
|
if (!decider.canSearchLibraryWith(sa, player)) {
|
||||||
fetchList.removeAll(player.getCardsIn(ZoneType.Library));
|
fetchList.removeAll(player.getCardsIn(ZoneType.Library));
|
||||||
// "if you do/sb does, shuffle" is not mandatory (usually a triggered ability), should has this param.
|
// "if you do/sb does, shuffle" is not mandatory (usually a triggered ability), should has this param.
|
||||||
// "then shuffle" is mandatory
|
// "then shuffle" is mandatory
|
||||||
|
|||||||
@@ -2965,4 +2965,19 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canSearchLibraryWith(SpellAbility sa, Player targetPlayer) {
|
||||||
|
if (sa == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hasKeyword("CantSearchLibrary")) {
|
||||||
|
return false;
|
||||||
|
} else if (targetPlayer != null && targetPlayer.equals(sa.getActivatingPlayer())
|
||||||
|
&& hasKeyword("Spells and abilities you control can't cause you to search your library.")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
forge-gui/res/cardsfolder/a/ashiok_dream_render.txt
Normal file
8
forge-gui/res/cardsfolder/a/ashiok_dream_render.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Ashiok, Dream Render
|
||||||
|
ManaCost:1 UB UB
|
||||||
|
Types:Legendary Planeswalker Ashiok
|
||||||
|
Loyalty:5
|
||||||
|
S:Mode$ Continuous | Affected$ Opponent | AddKeyword$ Spells and abilities you control can't cause you to search your library. | Description$ Spells and abilities your opponents control can't cause their controller to search their library.
|
||||||
|
A:AB$ Mill | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | NumCards$ 4 | ValidTgts$ Player | TgtPrompt$ Choose a player | SubAbility$ DBExileGrave | SpellDescription$ Target player puts the top four cards of their library into their graveyard. Then exile each opponent's graveyard.
|
||||||
|
SVar:DBExileGrave:DB$ ChangeZoneAll | Origin$ Graveyard | Destination$ Exile | Defined$ Opponent | ChangeType$ Card
|
||||||
|
Oracle:Spells and abilities your opponents control can't cause their controller to search their library.\n[-1]: Target player puts the top four cards of their library into their graveyard. Then exile each opponent's graveyard.
|
||||||
Reference in New Issue
Block a user