mirror of
https://github.com/correl/mage.git
synced 2024-12-25 11:11:16 +00:00
Fixed Thousand-Year Storm and added hints to Aetherflux Reservoir and Sentinel Tower (#6645)
This commit is contained in:
parent
13f7f2a035
commit
4dc99fbb58
3 changed files with 116 additions and 52 deletions
|
@ -10,6 +10,7 @@ import mage.abilities.dynamicvalue.DynamicValue;
|
|||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -28,12 +29,14 @@ public final class AetherfluxReservoir extends CardImpl {
|
|||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
|
||||
|
||||
// Whenever you cast a spell, you gain 1 life for each spell you've cast this turn.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(new GainLifeEffect(new AetherfluxReservoirDynamicValue()), false));
|
||||
Ability abilityGainLife = new SpellCastControllerTriggeredAbility(new GainLifeEffect(new AetherfluxReservoirDynamicValue()), false);
|
||||
abilityGainLife.addHint(new ValueHint("You've cast spells this turn", new AetherfluxReservoirDynamicValue()));
|
||||
this.addAbility(abilityGainLife);
|
||||
|
||||
// Pay 50 life: Aetherflux Reservoir deals 50 damage to any target.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(50), new PayLifeCost(50));
|
||||
ability.addTarget(new TargetAnyTarget());
|
||||
this.addAbility(ability);
|
||||
Ability abilityPayLife = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(50), new PayLifeCost(50));
|
||||
abilityPayLife.addTarget(new TargetAnyTarget());
|
||||
this.addAbility(abilityPayLife);
|
||||
}
|
||||
|
||||
public AetherfluxReservoir(final AetherfluxReservoir card) {
|
||||
|
|
|
@ -2,10 +2,13 @@ package mage.cards.s;
|
|||
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SpellCastAllTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -44,13 +47,18 @@ public final class SentinelTower extends CardImpl {
|
|||
|
||||
class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility {
|
||||
|
||||
private String damageInfo;
|
||||
|
||||
SentinelTowerTriggeredAbility() {
|
||||
super(new DamageTargetEffect(0), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false);
|
||||
this.addTarget(new TargetAnyTarget());
|
||||
this.addHint(new ValueHint("There were cast instant and sorcery this turn", SentinelTowerSpellsCastValue.instance));
|
||||
this.damageInfo = null;
|
||||
}
|
||||
|
||||
SentinelTowerTriggeredAbility(final SentinelTowerTriggeredAbility effect) {
|
||||
super(effect);
|
||||
this.damageInfo = effect.damageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,6 +86,7 @@ class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility {
|
|||
break;
|
||||
}
|
||||
}
|
||||
damageInfo = " (<b>" + damageToDeal + " damage</b>)";
|
||||
for (Effect effect : this.getEffects()) {
|
||||
if (effect instanceof DamageTargetEffect) {
|
||||
((DamageTargetEffect) effect).setAmount(StaticValue.get(damageToDeal));
|
||||
|
@ -92,7 +101,8 @@ class SentinelTowerTriggeredAbility extends SpellCastAllTriggeredAbility {
|
|||
public String getRule() {
|
||||
return "Whenever an instant or sorcery spell is cast during your turn, "
|
||||
+ "{this} deals damage to any target equal to 1 "
|
||||
+ "plus the number of instant and sorcery spells cast before that spell this turn.";
|
||||
+ "plus the number of instant and sorcery spells cast before that spell this turn."
|
||||
+ (damageInfo != null ? damageInfo : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,3 +134,36 @@ class SentinelTowerWatcher extends Watcher {
|
|||
return spellsThisTurn;
|
||||
}
|
||||
}
|
||||
|
||||
enum SentinelTowerSpellsCastValue implements DynamicValue {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
SentinelTowerWatcher watcher = game.getState().getWatcher(SentinelTowerWatcher.class);
|
||||
if (watcher == null) {
|
||||
return 0;
|
||||
}
|
||||
List<MageObjectReference> spellsCast = watcher.getSpellsThisTurn();
|
||||
if (spellsCast == null) {
|
||||
return 0;
|
||||
}
|
||||
return spellsCast.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SentinelTowerSpellsCastValue copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "There was an instant or sorcery spell in this turn";
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
|
@ -13,7 +15,7 @@ import mage.constants.CardType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterInstantOrSorcerySpell;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
|
@ -23,9 +25,11 @@ import mage.watchers.Watcher;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
* @author jasc7636
|
||||
*/
|
||||
public final class ThousandYearStorm extends CardImpl {
|
||||
|
||||
|
@ -33,7 +37,7 @@ public final class ThousandYearStorm extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}{R}");
|
||||
|
||||
// Whenever you cast an instant or sorcery spell, copy it for each other instant and sorcery spell you've cast before it this turn. You may choose new targets for the copies.
|
||||
this.addAbility(new ThousandYearStormAbility());
|
||||
this.addAbility(new ThousandYearStormAbility(), new ThousandYearStormWatcher());
|
||||
}
|
||||
|
||||
public ThousandYearStorm(final ThousandYearStorm card) {
|
||||
|
@ -48,12 +52,12 @@ public final class ThousandYearStorm extends CardImpl {
|
|||
|
||||
class ThousandYearStormAbility extends SpellCastControllerTriggeredAbility {
|
||||
|
||||
String stormCountInfo = null;
|
||||
private String stormCountInfo;
|
||||
|
||||
public ThousandYearStormAbility() {
|
||||
super(Zone.BATTLEFIELD, new ThousandYearStormEffect(), new FilterInstantOrSorcerySpell(), false, true);
|
||||
this.addHint(new ValueHint("You've cast instant and sorcery this turn", ThousandYearSpellsCastThatTurnValue.instance));
|
||||
this.addWatcher(new ThousandYearWatcher());
|
||||
super(Zone.BATTLEFIELD, new ThousandYearStormEffect(), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false, true);
|
||||
this.addHint(new ValueHint("You've cast instant and sorcery this turn", ThousandYearStormSpellsCastThatTurnValue.instance));
|
||||
this.stormCountInfo = null;
|
||||
}
|
||||
|
||||
public ThousandYearStormAbility(final ThousandYearStormAbility ability) {
|
||||
|
@ -63,12 +67,33 @@ class ThousandYearStormAbility extends SpellCastControllerTriggeredAbility {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
// save storm count info, real count will be calculated to stack ability in resolve effect only
|
||||
if (super.checkTrigger(event, game)) {
|
||||
int stormCount = ThousandYearSpellsCastThatTurnValue.instance.calculate(game, this, null);
|
||||
stormCountInfo = " (<b>storm count: " + Math.max(0, stormCount - 1) + "</b>) ";
|
||||
ThousandYearStormWatcher watcher = game.getState().getWatcher(ThousandYearStormWatcher.class);
|
||||
if (watcher == null) {
|
||||
return false;
|
||||
}
|
||||
UUID playerId = event.getPlayerId();
|
||||
List<MageObjectReference> spellsCast = watcher.getSpellsThisTurn(playerId);
|
||||
MageObject object = game.getObject(event.getTargetId());
|
||||
if (object == null || spellsCast == null) {
|
||||
return false;
|
||||
}
|
||||
int stormCount = 0;
|
||||
for (MageObjectReference mor : spellsCast) {
|
||||
stormCount++;
|
||||
if (mor.refersTo(object, game)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
stormCount = Math.max(0, stormCount - 1);
|
||||
stormCountInfo = " (<b>storm count: " + stormCount + "</b>) ";
|
||||
for (Effect effect : this.getEffects()) {
|
||||
if (effect instanceof ThousandYearStormEffect) {
|
||||
((ThousandYearStormEffect) effect).setStormCount(stormCount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -85,13 +110,16 @@ class ThousandYearStormAbility extends SpellCastControllerTriggeredAbility {
|
|||
}
|
||||
|
||||
class ThousandYearStormEffect extends OneShotEffect {
|
||||
private int stormCount;
|
||||
|
||||
public ThousandYearStormEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.stormCount = -1;
|
||||
}
|
||||
|
||||
public ThousandYearStormEffect(final ThousandYearStormEffect effect) {
|
||||
super(effect);
|
||||
this.stormCount = effect.stormCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,82 +130,72 @@ class ThousandYearStormEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Spell spell = game.getSpellOrLKIStack(getTargetPointer().getFirst(game, source));
|
||||
Player controller = spell != null ? game.getPlayer(spell.getControllerId()) : null;
|
||||
if (spell != null && controller != null) {
|
||||
ThousandYearWatcher watcher = game.getState().getWatcher(ThousandYearWatcher.class);
|
||||
if (watcher != null) {
|
||||
String stateSearchId = spell.getId().toString() + source.getSourceId().toString();
|
||||
// recall only the spells cast before it
|
||||
int numberOfCopies = 0;
|
||||
if (game.getState().getValue(stateSearchId) != null) {
|
||||
numberOfCopies = (int) game.getState().getValue(stateSearchId);
|
||||
}
|
||||
if (numberOfCopies > 0) {
|
||||
spell.createCopyOnStack(game, source, source.getControllerId(), true, numberOfCopies);
|
||||
}
|
||||
if (stormCount >= 0 && spell != null) {
|
||||
spell.createCopyOnStack(game, source, source.getControllerId(), true, stormCount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setStormCount(int stormCount) {
|
||||
this.stormCount = stormCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
return "copy it for each other instant and sorcery spell you've cast before it this turn. You may choose new targets for the copies";
|
||||
}
|
||||
}
|
||||
|
||||
class ThousandYearWatcher extends Watcher {
|
||||
class ThousandYearStormWatcher extends Watcher {
|
||||
|
||||
private final Map<UUID, Integer> amountOfInstantSorcerySpellsCastOnCurrentTurn = new HashMap<>();
|
||||
private final Map<UUID, List<MageObjectReference>> spellsThisTurn = new HashMap<>();
|
||||
|
||||
public ThousandYearWatcher() {
|
||||
public ThousandYearStormWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST && !sourceId.equals(event.getTargetId())) {
|
||||
Spell spell = game.getSpellOrLKIStack(event.getTargetId());
|
||||
if (spell != null && spell.isInstantOrSorcery()) {
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
MageObject object = game.getObject(event.getTargetId());
|
||||
if (object != null && (object.isInstant() || object.isSorcery())) {
|
||||
UUID playerId = event.getPlayerId();
|
||||
if (playerId != null) {
|
||||
String stateSearchId = spell.getId().toString() + sourceId.toString();
|
||||
// calc current spell
|
||||
amountOfInstantSorcerySpellsCastOnCurrentTurn.putIfAbsent(playerId, 0);
|
||||
amountOfInstantSorcerySpellsCastOnCurrentTurn.compute(playerId, (k, a) -> a + 1);
|
||||
// remember only the spells cast before it
|
||||
game.getState().setValue(stateSearchId, amountOfInstantSorcerySpellsCastOnCurrentTurn.get(playerId) - 1);
|
||||
}
|
||||
List<MageObjectReference> spellsCast = spellsThisTurn.getOrDefault(playerId, new ArrayList<MageObjectReference>());
|
||||
spellsCast.add(new MageObjectReference(object, game));
|
||||
spellsThisTurn.put(playerId, spellsCast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
amountOfInstantSorcerySpellsCastOnCurrentTurn.clear();
|
||||
for (List<MageObjectReference> mor : spellsThisTurn.values()) {
|
||||
mor.clear();
|
||||
}
|
||||
spellsThisTurn.clear();
|
||||
}
|
||||
|
||||
public int getAmountOfSpellsPlayerCastOnCurrentTurn(UUID playerId) {
|
||||
return amountOfInstantSorcerySpellsCastOnCurrentTurn.getOrDefault(playerId, 0);
|
||||
public List<MageObjectReference> getSpellsThisTurn(UUID playerId) {
|
||||
return spellsThisTurn.getOrDefault(playerId, new ArrayList<MageObjectReference>());
|
||||
}
|
||||
}
|
||||
|
||||
enum ThousandYearSpellsCastThatTurnValue implements DynamicValue {
|
||||
enum ThousandYearStormSpellsCastThatTurnValue implements DynamicValue {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
ThousandYearWatcher watcher = game.getState().getWatcher(ThousandYearWatcher.class);
|
||||
ThousandYearStormWatcher watcher = game.getState().getWatcher(ThousandYearStormWatcher.class);
|
||||
if (watcher == null) {
|
||||
return 0;
|
||||
}
|
||||
return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(sourceAbility.getControllerId());
|
||||
return watcher.getSpellsThisTurn(sourceAbility.getControllerId()).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThousandYearSpellsCastThatTurnValue copy() {
|
||||
public ThousandYearStormSpellsCastThatTurnValue copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue