forked from External/mage
Create common class for "when target dies this turn" delayed triggers (#9722)
Fixes #9716. Fixes #9719.
This commit is contained in:
parent
afb7d75007
commit
10d7acb4b5
74 changed files with 397 additions and 1628 deletions
|
|
@ -56,14 +56,7 @@ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
*
|
||||
* @param game
|
||||
*/
|
||||
public void initOnAdding(Game game) {
|
||||
|
||||
}
|
||||
|
||||
public void init(Game game) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.getTargetPointer().init(game, this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInactive(Game game) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
package mage.abilities.common.delayed;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
* @author awjackson
|
||||
*/
|
||||
public class WhenTargetDiesDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||
|
||||
protected MageObjectReference mor;
|
||||
private final SetTargetPointer setTargetPointer;
|
||||
|
||||
public WhenTargetDiesDelayedTriggeredAbility(Effect effect) {
|
||||
this(effect, SetTargetPointer.NONE);
|
||||
}
|
||||
|
||||
public WhenTargetDiesDelayedTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) {
|
||||
this(effect, Duration.EndOfTurn, setTargetPointer);
|
||||
}
|
||||
|
||||
public WhenTargetDiesDelayedTriggeredAbility(Effect effect, Duration duration, SetTargetPointer setTargetPointer) {
|
||||
super(effect, duration, true);
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
setTriggerPhrase("When that creature dies" + (duration == Duration.EndOfTurn ? " this turn, " : ", "));
|
||||
}
|
||||
|
||||
public WhenTargetDiesDelayedTriggeredAbility(final WhenTargetDiesDelayedTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.mor = ability.mor;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WhenTargetDiesDelayedTriggeredAbility copy() {
|
||||
return new WhenTargetDiesDelayedTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Game game) {
|
||||
mor = new MageObjectReference(getFirstTarget(), game);
|
||||
getTargets().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (!zEvent.isDiesEvent()) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = zEvent.getTarget();
|
||||
if (mor == null || !mor.refersTo(permanent, game)) {
|
||||
return false;
|
||||
}
|
||||
switch (setTargetPointer) {
|
||||
case CARD:
|
||||
// card in graveyard
|
||||
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
||||
break;
|
||||
case PERMANENT:
|
||||
// LKI of permanent
|
||||
getEffects().setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game)));
|
||||
break;
|
||||
case PLAYER:
|
||||
// LKI permanent's controller
|
||||
getEffects().setTargetPointer(new FixedTarget(permanent.getControllerId()));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,28 +14,28 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
|
|||
|
||||
protected DelayedTriggeredAbility ability;
|
||||
protected boolean copyTargets;
|
||||
protected boolean initAbility;
|
||||
protected String rulePrefix;
|
||||
|
||||
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability) {
|
||||
this(ability, true);
|
||||
}
|
||||
|
||||
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability, boolean copyTargets) {
|
||||
this(ability, copyTargets, false);
|
||||
this(ability, copyTargets, "");
|
||||
}
|
||||
|
||||
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability, boolean copyTargets, boolean initAbility) {
|
||||
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability, boolean copyTargets, String rulePrefix) {
|
||||
super(ability.getEffects().getOutcome(ability));
|
||||
this.ability = ability;
|
||||
this.copyTargets = copyTargets;
|
||||
this.initAbility = initAbility;
|
||||
this.rulePrefix = rulePrefix;
|
||||
}
|
||||
|
||||
public CreateDelayedTriggeredAbilityEffect(final CreateDelayedTriggeredAbilityEffect effect) {
|
||||
super(effect);
|
||||
this.ability = effect.ability.copy();
|
||||
this.copyTargets = effect.copyTargets;
|
||||
this.initAbility = effect.initAbility;
|
||||
this.rulePrefix = effect.rulePrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -56,9 +56,6 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (initAbility) {
|
||||
delayedAbility.init(game);
|
||||
}
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -69,7 +66,7 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
|
|||
return staticText;
|
||||
}
|
||||
if (ability.getRuleVisible()) {
|
||||
return ability.getRule();
|
||||
return rulePrefix + ability.getRule();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
|
|||
|
||||
private boolean tapped;
|
||||
protected boolean returnFromExileZoneOnly;
|
||||
private String returnName = "that card";
|
||||
private String returnUnderControlName = "its owner's";
|
||||
|
||||
/**
|
||||
* @param returnFromExileZoneOnly see https://github.com/magefree/mage/issues/5151
|
||||
|
|
@ -29,28 +27,20 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
|
|||
* return exiled card - true
|
||||
*/
|
||||
public ReturnToBattlefieldUnderOwnerControlTargetEffect(boolean tapped, boolean returnFromExileZoneOnly) {
|
||||
this(tapped, returnFromExileZoneOnly, "that card");
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlTargetEffect(boolean tapped, boolean returnFromExileZoneOnly, String description) {
|
||||
super(Outcome.Benefit);
|
||||
this.tapped = tapped;
|
||||
this.returnFromExileZoneOnly = returnFromExileZoneOnly;
|
||||
|
||||
updateText();
|
||||
staticText = "return " + description + " to the battlefield " + (tapped ? "tapped " : "") + "under its owner's control";
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlTargetEffect(final ReturnToBattlefieldUnderOwnerControlTargetEffect effect) {
|
||||
super(effect);
|
||||
this.tapped = effect.tapped;
|
||||
this.returnFromExileZoneOnly = effect.returnFromExileZoneOnly;
|
||||
this.returnName = effect.returnName;
|
||||
this.returnUnderControlName = effect.returnUnderControlName;
|
||||
|
||||
updateText();
|
||||
}
|
||||
|
||||
// TODO: This does not generate correct text, the ", then" should be from .concatBy, see Angelic Renewal for a card with incorrect text
|
||||
private void updateText() {
|
||||
this.staticText = ", then return " + this.returnName
|
||||
+ " to the battlefield" + (tapped ? " tapped" : "")
|
||||
+ " under " + this.returnUnderControlName + " control";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -92,11 +82,4 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderOwnerControlTargetEffect withReturnNames(String returnName, String returnUnderControlName) {
|
||||
this.returnName = returnName;
|
||||
this.returnUnderControlName = returnUnderControlName;
|
||||
updateText();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,17 +20,13 @@ import java.util.UUID;
|
|||
public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffect {
|
||||
|
||||
private boolean returnFromExileZoneOnly;
|
||||
private boolean tapped;
|
||||
private boolean attacking;
|
||||
private String returnName = "that card";
|
||||
private String returnUnderControlName = "your";
|
||||
|
||||
public ReturnToBattlefieldUnderYourControlTargetEffect() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean returnFromExileZoneOnly) {
|
||||
this(returnFromExileZoneOnly, false, false);
|
||||
this(returnFromExileZoneOnly, "that card");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,31 +34,15 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
|
|||
* return it or that card - false
|
||||
* return exiled card - true
|
||||
*/
|
||||
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean returnFromExileZoneOnly, boolean tapped, boolean attacking) {
|
||||
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean returnFromExileZoneOnly, String description) {
|
||||
super(Outcome.Benefit);
|
||||
this.returnFromExileZoneOnly = returnFromExileZoneOnly;
|
||||
this.tapped = tapped;
|
||||
this.attacking = attacking;
|
||||
|
||||
updateText();
|
||||
staticText = "return " + description + " to the battlefield under your control";
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderYourControlTargetEffect(final ReturnToBattlefieldUnderYourControlTargetEffect effect) {
|
||||
super(effect);
|
||||
this.returnFromExileZoneOnly = effect.returnFromExileZoneOnly;
|
||||
this.tapped = effect.tapped;
|
||||
this.attacking = effect.attacking;
|
||||
this.returnName = effect.returnName;
|
||||
this.returnUnderControlName = effect.returnUnderControlName;
|
||||
|
||||
updateText();
|
||||
}
|
||||
|
||||
private void updateText() {
|
||||
this.staticText = ", then return " + returnName + " to the battlefield under " + returnUnderControlName + " control"
|
||||
+ (tapped ? " tapped" : "")
|
||||
+ (tapped && attacking ? " and" : "")
|
||||
+ (attacking ? " attacking" : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -98,23 +78,11 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
|
|||
} else {
|
||||
cardsToBattlefield.addAll(getTargetPointer().getTargets(game, source));
|
||||
}
|
||||
|
||||
for (Card card : cardsToBattlefield.getCards(game)) {
|
||||
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, false, null)) {
|
||||
if (attacking) {
|
||||
game.getCombat().addAttackingCreature(card.getId(), game);
|
||||
}
|
||||
}
|
||||
if (!cardsToBattlefield.isEmpty()) {
|
||||
controller.moveCards(cardsToBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, false, false, false, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ReturnToBattlefieldUnderYourControlTargetEffect withReturnNames(String returnName, String returnUnderControlName) {
|
||||
this.returnName = returnName;
|
||||
this.returnUnderControlName = returnUnderControlName;
|
||||
updateText();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public class AddCountersControllerEffect extends OneShotEffect {
|
|||
super(Outcome.Benefit);
|
||||
this.counter = counter.copy();
|
||||
this.enchantedEquipped = enchantedEquipped;
|
||||
staticText = "its controller gets " + counter.getDescription();
|
||||
staticText = (enchantedEquipped ? "its controller gets " : "you get ") + counter.getDescription();
|
||||
}
|
||||
|
||||
public AddCountersControllerEffect(final AddCountersControllerEffect effect) {
|
||||
|
|
|
|||
|
|
@ -1985,10 +1985,7 @@ public abstract class GameImpl implements Game {
|
|||
newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId()));
|
||||
newAbility.setSourcePermanentTransformCount(this);
|
||||
}
|
||||
newAbility.initOnAdding(this);
|
||||
// ability.init is called as the ability triggeres not now.
|
||||
// If a FixedTarget pointer is already set from the effect setting up this delayed ability
|
||||
// it has to be already initialized so it won't be overwitten as the ability triggers
|
||||
newAbility.init(this);
|
||||
getState().addDelayedTriggeredAbility(newAbility);
|
||||
return newAbility.getId();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue