-
Notifications
You must be signed in to change notification settings - Fork 785
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[STX] Implement Ecological Appreciation #7732
Merged
JayDi85
merged 4 commits into
magefree:master
from
htrajan:stx-implement-ecological-appreciation
Apr 14, 2021
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package mage.cards.e; | ||
|
||
import com.google.common.collect.Sets; | ||
import mage.MageObject; | ||
import mage.abilities.Ability; | ||
import mage.abilities.effects.OneShotEffect; | ||
import mage.abilities.effects.common.ExileSpellEffect; | ||
import mage.cards.*; | ||
import mage.constants.CardType; | ||
import mage.constants.ComparisonType; | ||
import mage.constants.Outcome; | ||
import mage.constants.Zone; | ||
import mage.filter.FilterCard; | ||
import mage.filter.StaticFilters; | ||
import mage.filter.common.FilterCreatureCard; | ||
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; | ||
import mage.game.Game; | ||
import mage.players.Player; | ||
import mage.target.TargetCard; | ||
import mage.target.common.TargetCardInLibrary; | ||
import mage.target.common.TargetCardInYourGraveyard; | ||
import mage.target.common.TargetOpponent; | ||
import mage.util.CardUtil; | ||
|
||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* | ||
* @author htrajan | ||
*/ | ||
public final class EcologicalAppreciation extends CardImpl { | ||
|
||
public EcologicalAppreciation(UUID ownerId, CardSetInfo setInfo) { | ||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{2}{G}"); | ||
|
||
// Search your library and graveyard for up to four creature cards with different names that each have mana value X or less and reveal them. An opponent chooses two of those cards. Shuffle the chosen cards into your library and put the rest onto the battlefield. Exile Ecological Appreciation. | ||
this.getSpellAbility().addEffect(new EcologicalAppreciationEffect()); | ||
this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); | ||
} | ||
|
||
private EcologicalAppreciation(final EcologicalAppreciation card) { | ||
super(card); | ||
} | ||
|
||
@Override | ||
public EcologicalAppreciation copy() { | ||
return new EcologicalAppreciation(this); | ||
} | ||
} | ||
|
||
class EcologicalAppreciationEffect extends OneShotEffect { | ||
|
||
EcologicalAppreciationEffect() { | ||
super(Outcome.Benefit); | ||
staticText = "search your library and graveyard for up to four creature cards with different names that each have mana value X or less and reveal them. An opponent chooses two of those cards. Shuffle the chosen cards into your library and put the rest onto the battlefield"; | ||
} | ||
|
||
private EcologicalAppreciationEffect(final EcologicalAppreciationEffect effect) { | ||
super(effect); | ||
} | ||
|
||
@Override | ||
public EcologicalAppreciationEffect copy() { | ||
return new EcologicalAppreciationEffect(this); | ||
} | ||
|
||
@Override | ||
public boolean apply(Game game, Ability source) { | ||
Player player = game.getPlayer(source.getControllerId()); | ||
if (player == null) { | ||
return false; | ||
} | ||
int xValue = source.getManaCostsToPay().getX(); | ||
FilterCard filter = new FilterCreatureCard(); | ||
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); | ||
TargetCard targetCardsInLibrary = new TargetCardInLibrary(0, 4, filter) { | ||
@Override | ||
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { | ||
if (!super.canTarget(playerId, id, source, game)) { | ||
return false; | ||
} | ||
Card card = game.getCard(id); | ||
Set<Card> disallowedCards = this.getTargets().stream() | ||
.map(game::getCard) | ||
.collect(Collectors.toSet()); | ||
return isValidTarget(card, disallowedCards); | ||
} | ||
}; | ||
targetCardsInLibrary.setNotTarget(true); | ||
targetCardsInLibrary.withChooseHint("Step 1 of 2: Search library"); | ||
player.choose(Outcome.PutCreatureInPlay, new CardsImpl(player.getLibrary().getCards(game)), targetCardsInLibrary, game); | ||
Cards cards = new CardsImpl(targetCardsInLibrary.getTargets()); | ||
|
||
boolean status = !cards.isEmpty(); | ||
|
||
if (status) { | ||
int remainingCards = 4 - cards.size(); | ||
if (remainingCards > 0) { | ||
TargetCard targetCardsInGY = new TargetCardInYourGraveyard(0, remainingCards, filter) { | ||
@Override | ||
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { | ||
if (!super.canTarget(playerId, id, source, game)) { | ||
return false; | ||
} | ||
Card card = game.getCard(id); | ||
Set<Card> disallowedCards = this.getTargets().stream() | ||
.map(game::getCard) | ||
.collect(Collectors.toSet()); | ||
return isValidTarget(card, Sets.union(disallowedCards, cards.getCards(game))); | ||
} | ||
}; | ||
targetCardsInGY.setNotTarget(true); | ||
targetCardsInGY.withChooseHint("Step 2 of 2: Search graveyard"); | ||
player.choose(Outcome.PutCreatureInPlay, new CardsImpl(player.getGraveyard().getCards(game)), targetCardsInGY, game); | ||
cards.addAll(targetCardsInGY.getTargets()); | ||
} | ||
|
||
TargetOpponent targetOpponent = new TargetOpponent(); | ||
targetOpponent.setNotTarget(true); | ||
player.choose(outcome, targetOpponent, source.getSourceId(), game); | ||
Player opponent = game.getPlayer(targetOpponent.getFirstTarget()); | ||
|
||
if (opponent == null) { | ||
status = false; | ||
} | ||
|
||
if (status) { | ||
TargetCard chosenCards = new TargetCard(2, Zone.ALL, StaticFilters.FILTER_CARD); | ||
chosenCards.setNotTarget(true); | ||
opponent.choose(outcome, cards, chosenCards, game); | ||
Cards toShuffle = new CardsImpl(chosenCards.getTargets().stream() | ||
.map(game::getCard) | ||
.collect(Collectors.toList())); | ||
|
||
player.putCardsOnTopOfLibrary(toShuffle, game, source, false); | ||
cards.removeAll(toShuffle); | ||
|
||
player.moveCards(cards, Zone.BATTLEFIELD, source, game); | ||
} | ||
} | ||
|
||
player.shuffleLibrary(source, game); | ||
|
||
return status; | ||
} | ||
|
||
private boolean isValidTarget(Card target, Set<Card> disallowedCards) { | ||
return target != null && | ||
disallowedCards.stream() | ||
.filter(Objects::nonNull) | ||
.map(MageObject::getName) | ||
.noneMatch(name -> CardUtil.haveSameNames(name, target.getName())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use
target.withChooseHint
to inform user in choose dialog about current step or additional info. Example: "step 1 of 2, from library".There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added