* Reworked flashback ability (fixes #4482 #3324 #215 #3435 #3883 #3337 #2183 #2447).

This commit is contained in:
LevelX2 2018-02-18 02:52:16 +01:00
parent 2e827a50ec
commit d80d588963
9 changed files with 107 additions and 122 deletions

View file

@ -32,14 +32,13 @@ import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.cards.SplitCard;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityCastMode;
import mage.constants.SpellAbilityType;
import mage.constants.TimingRule;
import mage.constants.Zone;
@ -66,23 +65,21 @@ import mage.target.targetpointer.FixedTarget;
public class FlashbackAbility extends SpellAbility {
private String abilityName;
private SpellAbility spellAbilityToResolve;
public FlashbackAbility(Cost cost, TimingRule timingRule) {
super(null, "", Zone.GRAVEYARD);
super(null, "", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE, SpellAbilityCastMode.FLASHBACK);
this.setAdditionalCostsRuleVisible(false);
this.name = "Flashback " + cost.getText();
this.addEffect(new FlashbackEffect());
this.addCost(cost);
this.timing = timingRule;
this.usesStack = false;
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
setCostModificationActive(false);
}
public FlashbackAbility(final FlashbackAbility ability) {
super(ability);
this.spellAbilityType = ability.spellAbilityType;
this.abilityName = ability.abilityName;
this.spellAbilityToResolve = ability.spellAbilityToResolve;
}
@Override
@ -108,6 +105,47 @@ public class FlashbackAbility extends SpellAbility {
return false;
}
@Override
public SpellAbility getSpellAbilityToResolve(Game game) {
Card card = game.getCard(getSourceId());
if (card != null) {
if (spellAbilityToResolve == null) {
SpellAbility spellAbilityCopy = null;
if (card.isSplitCard()) {
if (((SplitCard) card).getLeftHalfCard().getName().equals(abilityName)) {
spellAbilityCopy = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
} else if (((SplitCard) card).getRightHalfCard().getName().equals(abilityName)) {
spellAbilityCopy = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
}
} else {
spellAbilityCopy = card.getSpellAbility().copy();
}
if (spellAbilityCopy == null) {
return null;
}
spellAbilityCopy.setId(this.getId());
spellAbilityCopy.getManaCosts().clear();
spellAbilityCopy.getManaCostsToPay().clear();
spellAbilityCopy.getCosts().addAll(this.getCosts());
spellAbilityCopy.addCost(this.getManaCosts());
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
spellAbilityToResolve = spellAbilityCopy;
ContinuousEffect effect = new FlashbackReplacementEffect();
effect.setTargetPointer(new FixedTarget(getSourceId(), game.getState().getZoneChangeCounter(getSourceId())));
game.addEffect(effect, this);
}
}
return spellAbilityToResolve;
}
@Override
public Costs<Cost> getCosts() {
if (spellAbilityToResolve == null) {
return super.getCosts();
}
return spellAbilityToResolve.getCosts();
}
@Override
public FlashbackAbility copy() {
return new FlashbackAbility(this);
@ -144,102 +182,18 @@ public class FlashbackAbility extends SpellAbility {
return sbRule.toString();
}
@Override
public void setSpellAbilityType(SpellAbilityType spellAbilityType) {
this.spellAbilityType = spellAbilityType;
}
@Override
public SpellAbilityType getSpellAbilityType() {
return this.spellAbilityType;
}
/**
* Used for split card sin PlayerImpl method:
* getOtherUseableActivatedAbilities
*
* @param abilityName
*/
public void setAbilityName(String abilityName) {
this.abilityName = abilityName;
}
}
class FlashbackEffect extends OneShotEffect {
public FlashbackEffect() {
super(Outcome.Benefit);
staticText = "";
}
public FlashbackEffect(final FlashbackEffect effect) {
super(effect);
}
@Override
public FlashbackEffect copy() {
return new FlashbackEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Card card = (Card) game.getObject(source.getSourceId());
if (card != null) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
SpellAbility spellAbility;
switch (((FlashbackAbility) source).getSpellAbilityType()) {
case SPLIT_LEFT:
spellAbility = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
break;
case SPLIT_RIGHT:
spellAbility = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
break;
default:
spellAbility = card.getSpellAbility().copy();
}
spellAbility.clear();
// set the payed flashback costs to the spell ability so abilities like Converge or calculation of {X} values work
spellAbility.getManaCostsToPay().clear();
spellAbility.getManaCostsToPay().addAll(source.getManaCosts());
spellAbility.getManaCosts().clear();
spellAbility.getManaCosts().addAll(source.getManaCosts());
// needed to get e.g. paid costs from Conflagrate
for (Cost cost : source.getCosts()) {
if (cost instanceof Costs) {
Costs<Cost> listOfCosts = (Costs<Cost>) cost;
for (Cost singleCost : listOfCosts) {
if (singleCost instanceof ManaCost) {
singleCost.clearPaid();
spellAbility.getManaCosts().add((ManaCost) singleCost);
spellAbility.getManaCostsToPay().add((ManaCost) singleCost);
} else {
spellAbility.getCosts().add(singleCost);
}
}
} else {
if (cost instanceof ManaCost) {
spellAbility.getManaCosts().add((ManaCost) cost);
spellAbility.getManaCostsToPay().add((ManaCost) cost);
} else {
spellAbility.getCosts().add(cost);
}
}
}
if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " flashbacks " + card.getLogName());
}
if (controller.cast(spellAbility, game, false)) {
ContinuousEffect effect = new FlashbackReplacementEffect();
effect.setTargetPointer(new FixedTarget(source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId())));
game.addEffect(effect, source);
}
return true;
}
}
return false;
}
}
class FlashbackReplacementEffect extends ReplacementEffectImpl {
public FlashbackReplacementEffect() {
@ -287,7 +241,7 @@ class FlashbackReplacementEffect extends ReplacementEffectImpl {
&& ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) {
int zcc = game.getState().getZoneChangeCounter(source.getSourceId());
if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() == zcc) {
if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == zcc) {
return true;
}