mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[FIC] Implement Lifestream's Blessing
This commit is contained in:
parent
db4b076b93
commit
c7006017ca
3 changed files with 235 additions and 0 deletions
141
Mage.Sets/src/mage/cards/l/LifestreamsBlessing.java
Normal file
141
Mage.Sets/src/mage/cards/l/LifestreamsBlessing.java
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
package mage.cards.l;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.keyword.ForetellAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class LifestreamsBlessing extends CardImpl {
|
||||
|
||||
public LifestreamsBlessing(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{G}{G}");
|
||||
|
||||
// Draw X cards, where X is the greatest power among creatures you controlled as you cast this spell. If this spell was cast from exile, you gain twice X life.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(LifestreamsBlessingValue.ONCE));
|
||||
this.getSpellAbility().addEffect(new GainLifeEffect(LifestreamsBlessingValue.TWICE)
|
||||
.setText("if this spell was cast from exile, you gain twice X life"));
|
||||
this.getSpellAbility().addWatcher(new LifestreamsBlessingWatcher());
|
||||
|
||||
// Foretell {4}{G}
|
||||
this.addAbility(new ForetellAbility(this, "{4}{G}"));
|
||||
}
|
||||
|
||||
private LifestreamsBlessing(final LifestreamsBlessing card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifestreamsBlessing copy() {
|
||||
return new LifestreamsBlessing(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum LifestreamsBlessingValue implements DynamicValue {
|
||||
ONCE(false),
|
||||
TWICE(true);
|
||||
private final boolean flag;
|
||||
|
||||
LifestreamsBlessingValue(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
if (flag && !Optional
|
||||
.ofNullable(sourceAbility)
|
||||
.map(Ability::getSourceId)
|
||||
.map(game::getSpell)
|
||||
.map(Spell::getFromZone)
|
||||
.map(Zone.EXILED::match)
|
||||
.orElse(false)) {
|
||||
return 0;
|
||||
}
|
||||
return (flag ? 2 : 1) * LifestreamsBlessingWatcher.getValue(game, sourceAbility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifestreamsBlessingValue copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "the greatest power among creatures you controlled as you cast this spell";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
}
|
||||
|
||||
class LifestreamsBlessingWatcher extends Watcher {
|
||||
|
||||
private final Map<MageObjectReference, Integer> map = new HashMap<>();
|
||||
|
||||
LifestreamsBlessingWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.SPELL_CAST) {
|
||||
return;
|
||||
}
|
||||
Spell spell = game.getSpell(event.getTargetId());
|
||||
if (spell == null) {
|
||||
return;
|
||||
}
|
||||
map.put(
|
||||
new MageObjectReference(spell.getSpellAbility().getSourceId(), game),
|
||||
game.getBattlefield()
|
||||
.getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE, spell.getControllerId(), game
|
||||
)
|
||||
.stream()
|
||||
.map(MageObject::getPower)
|
||||
.mapToInt(MageInt::getValue)
|
||||
.max()
|
||||
.orElse(0)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
map.clear();
|
||||
}
|
||||
|
||||
static int getValue(Game game, Ability source) {
|
||||
return game
|
||||
.getState()
|
||||
.getWatcher(LifestreamsBlessingWatcher.class)
|
||||
.map
|
||||
.getOrDefault(new MageObjectReference(
|
||||
source.getSourceId(), source.getSourceObjectZoneChangeCounter(), game
|
||||
), 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -226,6 +226,8 @@ public final class FinalFantasyCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Krile Baldesion", 86, Rarity.RARE, mage.cards.k.KrileBaldesion.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Legions to Ashes", 326, Rarity.RARE, mage.cards.l.LegionsToAshes.class));
|
||||
cards.add(new SetCardInfo("Lethal Scheme", 277, Rarity.RARE, mage.cards.l.LethalScheme.class));
|
||||
cards.add(new SetCardInfo("Lifestream's Blessing", 122, Rarity.RARE, mage.cards.l.LifestreamsBlessing.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lifestream's Blessing", 67, Rarity.RARE, mage.cards.l.LifestreamsBlessing.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Lightning Greaves", 349, Rarity.UNCOMMON, mage.cards.l.LightningGreaves.class));
|
||||
cards.add(new SetCardInfo("Lingering Souls", 245, Rarity.UNCOMMON, mage.cards.l.LingeringSouls.class));
|
||||
cards.add(new SetCardInfo("Locke, Treasure Hunter", 177, Rarity.RARE, mage.cards.l.LockeTreasureHunter.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
package org.mage.test.cards.single.fic;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class LifestreamsBlessingTest extends CardTestPlayerBase {
|
||||
|
||||
private static final String blessing = "Lifestream's Blessing";
|
||||
private static final String jackal = "Trained Jackal";
|
||||
private static final String bear = "Ashcoat Bear";
|
||||
private static final String giant = "Hill Giant";
|
||||
|
||||
@Test
|
||||
public void testRegular() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, jackal);
|
||||
addCard(Zone.BATTLEFIELD, playerB, giant);
|
||||
addCard(Zone.HAND, playerA, blessing);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, blessing);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 1);
|
||||
assertLife(playerA, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlashIn22() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6 + 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, jackal);
|
||||
addCard(Zone.BATTLEFIELD, playerB, giant);
|
||||
addCard(Zone.HAND, playerA, blessing);
|
||||
addCard(Zone.HAND, playerA, bear);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, blessing);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bear);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 1);
|
||||
assertLife(playerA, 20);
|
||||
}
|
||||
|
||||
private static final String twincast = "Twincast";
|
||||
|
||||
@Test
|
||||
public void testTwincast() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 6 + 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, jackal);
|
||||
addCard(Zone.BATTLEFIELD, playerB, giant);
|
||||
addCard(Zone.HAND, playerA, blessing);
|
||||
addCard(Zone.HAND, playerA, twincast);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, blessing);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, twincast, blessing);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 1);
|
||||
assertLife(playerA, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForetell() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, jackal);
|
||||
addCard(Zone.BATTLEFIELD, playerB, giant);
|
||||
addCard(Zone.HAND, playerA, blessing);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "For");
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "For");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 1 + 1);
|
||||
assertLife(playerA, 20 + 2);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue