- Fixed #8067. Included weirddan455 fixes to Kardur Doomscourge as well. Added support for "remove from combat" to the 2 cards. Note that attacking creatures put into the graveyard is a special case. Test will follow.

This commit is contained in:
jeffwadsworth 2021-07-31 16:46:11 -05:00
parent 9baa36c2e3
commit 43dbaf405b
5 changed files with 137 additions and 24 deletions

View file

@ -0,0 +1,121 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.common;
import java.util.List;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import static mage.game.events.GameEvent.EventType.DECLARE_ATTACKERS_STEP;
import static mage.game.events.GameEvent.EventType.END_COMBAT_STEP_POST;
import static mage.game.events.GameEvent.EventType.REMOVED_FROM_COMBAT;
import static mage.game.events.GameEvent.EventType.ZONE_CHANGE;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
/**
*
* @author weirddan455 and jeffwadsworth
*/
public class AttackingCreaturePutIntoGraveyardTriggeredAbility extends TriggeredAbilityImpl {
protected FilterPermanent filterPermanent;
private final boolean onlyToControllerGraveyard;
private final boolean itDies;
public AttackingCreaturePutIntoGraveyardTriggeredAbility(Effect effect, FilterPermanent filterPermanent, Boolean onlyToControllerGraveyard, Boolean itDies, Boolean optional) {
super(Zone.BATTLEFIELD, effect, optional);
this.filterPermanent = filterPermanent;
this.onlyToControllerGraveyard = onlyToControllerGraveyard;
this.itDies = itDies;
}
private AttackingCreaturePutIntoGraveyardTriggeredAbility(final AttackingCreaturePutIntoGraveyardTriggeredAbility ability) {
super(ability);
this.filterPermanent = ability.filterPermanent;
this.onlyToControllerGraveyard = ability.onlyToControllerGraveyard;
this.itDies = ability.itDies;
}
@Override
public AttackingCreaturePutIntoGraveyardTriggeredAbility copy() {
return new AttackingCreaturePutIntoGraveyardTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
switch (event.getType()) {
case DECLARE_ATTACKERS_STEP:
case END_COMBAT_STEP_POST:
case ZONE_CHANGE:
case REMOVED_FROM_COMBAT:
return true;
default:
return false;
}
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
switch (event.getType()) {
case DECLARE_ATTACKERS_STEP:
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null
&& !filterPermanent.match(permanent, game)) {
return false;
}
game.getState().setValue(this.getSourceId() + "Attackers", game.getCombat().getAttackers());
return false;
case END_COMBAT_STEP_POST:
game.getState().setValue(this.getSourceId() + "Attackers", null);
return false;
case ZONE_CHANGE:
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD
&& zEvent.getToZone() == Zone.GRAVEYARD) {
if (onlyToControllerGraveyard
&& !this.isControlledBy(game.getOwnerId(zEvent.getTargetId()))) {
return false;
}
if (itDies
&& !zEvent.isDiesEvent()) {
return false;
}
List<UUID> attackers = (List<UUID>) game.getState().getValue(this.getSourceId() + "Attackers");
return attackers != null
&& attackers.contains(zEvent.getTargetId());
}
case REMOVED_FROM_COMBAT:
// a card removed from combat is no longer an attacker or blocker so remove it from the list
if (game.isSimulation()) { // a simulated game will always choose to apply any triggered effect IE: Gustcloak Savior
return false;
}
List<UUID> attackersList = (List<UUID>) game.getState().getValue(this.getSourceId() + "Attackers");
if (attackersList != null
&& attackersList.contains(event.getTargetId())) {
attackersList.remove(event.getTargetId());
game.getState().setValue(this.getSourceId() + "Attackers", attackersList);
}
default:
return false;
}
}
@Override
public String getTriggerPhrase() {
if (itDies) {
return "Whenever " + filterPermanent.getMessage() + " dies, ";
}
return "Whenever " + filterPermanent.getMessage() + " is put into " + (onlyToControllerGraveyard ? "your" : "a")
+ " graveyard from the battlefield, ";
}
}

View file

@ -354,8 +354,8 @@ public class Combat implements Serializable, Copyable<Combat> {
if (game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId))
|| (!canBand && !canBandWithOther)
|| !player.chooseUse(Outcome.Benefit,
(isBanded ? "Band " + attacker.getLogName()
+ " with another " : "Form a band with " + attacker.getLogName() + " and an ")
(isBanded ? "Band " + attacker.getLogName()
+ " with another " : "Form a band with " + attacker.getLogName() + " and an ")
+ "attacking creature?", null, game)) {
break;
}
@ -573,7 +573,7 @@ public class Combat implements Serializable, Copyable<Combat> {
* Handle the blocker selection process
*
* @param blockController player that controls how to block, if null the
* defender is the controller
* defender is the controller
* @param game
*/
public void selectBlockers(Player blockController, Ability source, Game game) {
@ -1390,7 +1390,7 @@ public class Combat implements Serializable, Copyable<Combat> {
* @param playerId
* @param game
* @param solveBanding check whether also add creatures banded with
* attackerId
* attackerId
*/
public void addBlockingGroup(UUID blockerId, UUID attackerId, UUID playerId, Game game, boolean solveBanding) {
Permanent blocker = game.getPermanent(blockerId);
@ -1463,6 +1463,7 @@ public class Combat implements Serializable, Copyable<Combat> {
creature.clearBandedCards();
blockingGroups.remove(creatureId);
if (result && withInfo) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.REMOVED_FROM_COMBAT, creatureId, null, null));
game.informPlayers(creature.getLogName() + " removed from combat");
}
}

View file

@ -457,6 +457,7 @@ public class GameEvent implements Serializable {
ROOM_ENTERED,
VENTURE, VENTURED,
DUNGEON_COMPLETED,
REMOVED_FROM_COMBAT, // targetId id of permanent removed from combat
//custom events
CUSTOM_EVENT
}