mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Merge branch 'soulfire' into 'master'
CMR: Soulfire Eruption and support See merge request core-developers/forge!3347
This commit is contained in:
@@ -3,6 +3,7 @@ package forge.game.ability.effects;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import forge.GameCommand;
|
import forge.GameCommand;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
@@ -114,6 +115,18 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for a mixed list of target permanents and players, e.g. Soulfire Eruption
|
||||||
|
if (sa.hasParam("RepeatTargeted")) {
|
||||||
|
final List <GameObject> tgts = getTargets(sa);
|
||||||
|
if (tgts != null) {
|
||||||
|
for (final Object o : tgts) {
|
||||||
|
source.addRemembered(o);
|
||||||
|
AbilityUtils.resolve(repeat);
|
||||||
|
source.removeRemembered(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sa.hasParam("RepeatPlayers")) {
|
if (sa.hasParam("RepeatPlayers")) {
|
||||||
final FCollection<Player> repeatPlayers = AbilityUtils.getDefinedPlayers(source, sa.getParam("RepeatPlayers"), sa);
|
final FCollection<Player> repeatPlayers = AbilityUtils.getDefinedPlayers(source, sa.getParam("RepeatPlayers"), sa);
|
||||||
if (sa.hasParam("ClearRememberedBeforeLoop")) {
|
if (sa.hasParam("ClearRememberedBeforeLoop")) {
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.spellability;
|
package forge.game.spellability;
|
||||||
|
|
||||||
|
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 forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
@@ -25,7 +27,7 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerCollection;
|
import forge.util.collect.FCollection;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -39,98 +41,51 @@ import java.util.List;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class TargetChoices implements Cloneable {
|
public class TargetChoices implements Cloneable {
|
||||||
private int numTargeted = 0;
|
|
||||||
|
|
||||||
// Card or Player are legal targets.
|
private final FCollection<GameObject> targets = new FCollection<GameObject>();
|
||||||
private final CardCollection targetCards = new CardCollection();
|
|
||||||
private final PlayerCollection targetPlayers = new PlayerCollection();
|
|
||||||
private final List<SpellAbility> targetSpells = new ArrayList<>();
|
|
||||||
|
|
||||||
public final int getNumTargeted() {
|
public final int getNumTargeted() {
|
||||||
return numTargeted;
|
return targets.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getTotalTargetedCMC() {
|
public final int getTotalTargetedCMC() {
|
||||||
int totalCMC = 0;
|
int totalCMC = 0;
|
||||||
for (Card c : targetCards) {
|
for (Card c : Iterables.filter(targets, Card.class)) {
|
||||||
totalCMC += c.getCMC();
|
totalCMC += c.getCMC();
|
||||||
}
|
}
|
||||||
return totalCMC;
|
return totalCMC;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean add(final GameObject o) {
|
public final boolean add(final GameObject o) {
|
||||||
if (o instanceof Player) {
|
if (o instanceof Player || o instanceof Card || o instanceof SpellAbility) {
|
||||||
return addTarget((Player) o);
|
return targets.add(o);
|
||||||
} else if (o instanceof Card) {
|
|
||||||
return addTarget((Card) o);
|
|
||||||
} else if (o instanceof SpellAbility) {
|
|
||||||
return addTarget((SpellAbility) o);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean addTarget(final Card c) {
|
|
||||||
if (targetCards.add(c)) {
|
|
||||||
numTargeted++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean addTarget(final Player p) {
|
|
||||||
if (targetPlayers.add(p)) {
|
|
||||||
numTargeted++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean addTarget(final SpellAbility sa) {
|
|
||||||
if (!targetSpells.contains(sa)) {
|
|
||||||
targetSpells.add(sa);
|
|
||||||
numTargeted++;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean remove(final GameObject target) {
|
public final boolean remove(final GameObject target) {
|
||||||
// remove returns true if element was found in given list
|
// remove returns true if element was found in given list
|
||||||
if (targetCards.remove(target) || targetPlayers.remove(target) || targetSpells.remove(target)) {
|
return targets.remove(target);
|
||||||
numTargeted--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView getTargetCards() {
|
public final CardCollectionView getTargetCards() {
|
||||||
return targetCards;
|
return new CardCollection(Iterables.filter(targets, Card.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Iterable<Player> getTargetPlayers() {
|
public final Iterable<Player> getTargetPlayers() {
|
||||||
return targetPlayers;
|
return Iterables.filter(targets, Player.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Iterable<SpellAbility> getTargetSpells() {
|
public final Iterable<SpellAbility> getTargetSpells() {
|
||||||
return targetSpells;
|
return Iterables.filter(targets, SpellAbility.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<GameEntity> getTargetEntities() {
|
public final List<GameEntity> getTargetEntities() {
|
||||||
final List<GameEntity> tgts = new ArrayList<>();
|
return Lists.newArrayList(Iterables.filter(targets, GameEntity.class));
|
||||||
tgts.addAll(targetPlayers);
|
|
||||||
tgts.addAll(targetCards);
|
|
||||||
|
|
||||||
return tgts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<GameObject> getTargets() {
|
public final List<GameObject> getTargets() {
|
||||||
final List<GameObject> tgts = new ArrayList<>();
|
return this.targets;
|
||||||
tgts.addAll(targetPlayers);
|
|
||||||
tgts.addAll(targetCards);
|
|
||||||
tgts.addAll(targetSpells);
|
|
||||||
|
|
||||||
return tgts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -165,45 +120,41 @@ public class TargetChoices implements Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isTargetingAnyCard() {
|
public final boolean isTargetingAnyCard() {
|
||||||
return !targetCards.isEmpty();
|
return Iterables.any(targets, Predicates.instanceOf(Card.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isTargetingAnyPlayer() {
|
public final boolean isTargetingAnyPlayer() {
|
||||||
return !targetPlayers.isEmpty();
|
return Iterables.any(targets, Predicates.instanceOf(Player.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final boolean isTargetingAnySpell() {
|
public final boolean isTargetingAnySpell() {
|
||||||
return !targetSpells.isEmpty();
|
return Iterables.any(targets, Predicates.instanceOf(SpellAbility.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isTargeting(GameObject e) {
|
public final boolean isTargeting(GameObject e) {
|
||||||
return targetCards.contains(e) || targetSpells.contains(e) || targetPlayers.contains(e);
|
return targets.contains(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Card getFirstTargetedCard() {
|
public final Card getFirstTargetedCard() {
|
||||||
return Iterables.getFirst(targetCards, null);
|
return Iterables.getFirst(Iterables.filter(targets, Card.class), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Player getFirstTargetedPlayer() {
|
public final Player getFirstTargetedPlayer() {
|
||||||
return Iterables.getFirst(targetPlayers, null);
|
return Iterables.getFirst(getTargetPlayers(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final SpellAbility getFirstTargetedSpell() {
|
public final SpellAbility getFirstTargetedSpell() {
|
||||||
return Iterables.getFirst(targetSpells, null);
|
return Iterables.getFirst(getTargetSpells(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isEmpty() {
|
public final boolean isEmpty() {
|
||||||
return targetCards.isEmpty() && targetSpells.isEmpty() && targetPlayers.isEmpty();
|
return targets.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TargetChoices clone() {
|
public TargetChoices clone() {
|
||||||
TargetChoices tc = new TargetChoices();
|
TargetChoices tc = new TargetChoices();
|
||||||
tc.targetCards.addAll(targetCards);
|
tc.targets.addAll(targets);
|
||||||
tc.targetPlayers.addAll(targetPlayers);
|
|
||||||
tc.targetSpells.addAll(targetSpells);
|
|
||||||
tc.numTargeted = numTargeted;
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
forge-gui/res/cardsfolder/upcoming/soulfire_eruption.txt
Normal file
14
forge-gui/res/cardsfolder/upcoming/soulfire_eruption.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Name:Soulfire Eruption
|
||||||
|
ManaCost:6 R R R
|
||||||
|
Types:Sorcery
|
||||||
|
A:SP$ RepeatEach | Cost$ 6 R R R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Choose any number of target creatures, planeswalkers, and/or players | TargetMin$ 0 | TargetMax$ MaxTgt | References$ MaxTgt,MaxPl,MaxPerm | RepeatSubAbility$ DBDig | RepeatTargeted$ True | SubAbility$ DBEffect | StackDescription$ SpellDescription | SpellDescription$ Choose any number of target creatures, planeswalkers, and/or players. For each of them, exile the top card of your library, then CARDNAME deals damage equal to that card's converted mana cost to that permanent or player. You may play the exiled cards until the end of your next turn.
|
||||||
|
SVar:DBDig:DB$ Dig | Defined$ You | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | ImprintRevealed$ True | Reveal$ True | SubAbility$ DBDealDamage
|
||||||
|
SVar:DBDealDamage:DB$ DealDamage | Defined$ Remembered | NumDmg$ X | References$ X | SubAbility$ DBCleanup
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True
|
||||||
|
SVar:DBEffect:DB$ Effect | StaticAbilities$ STMayPlay | Duration$ UntilTheEndOfYourNextTurn | RememberObjects$ ValidExile Card.ExiledWithSource | ForgetOnMoved$ Exile
|
||||||
|
SVar:STMayPlay:Mode$ Continuous | Affected$ Card.IsRemembered | EffectZone$ Command | AffectedZone$ Exile | MayPlay$ True | Description$ You may play the exiled cards until the end of your next turn.
|
||||||
|
SVar:MaxTgt:SVar$MaxPl/Plus.MaxPerm
|
||||||
|
SVar:MaxPl:PlayerCountPlayers$Amount
|
||||||
|
SVar:MaxPerm:Count$Valid Creature,Planeswalker
|
||||||
|
SVar:X:Imprinted$CardManaCost
|
||||||
|
Oracle:Choose any number of target creatures, planeswalkers, and/or players. For each of them, exile the top card of your library, then Soulfire Eruption deals damage equal to that card's converted mana cost to that permanent or player. You may play the exiled cards until the end of your next turn.
|
||||||
Reference in New Issue
Block a user