mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
ONE: Elesh Norn, Mother of Machines and support (#2179)
* elesh_norn_mother_of_machines.txt * StaticAbilityDisableTriggers.java
This commit is contained in:
@@ -25,8 +25,6 @@ public enum GlobalRuleChange {
|
||||
alwaysWither ("All damage is dealt as though its source had wither."),
|
||||
attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."),
|
||||
manaBurn ("A player losing unspent mana causes that player to lose that much life."),
|
||||
noCreatureETBTriggers ("Creatures entering the battlefield don't cause abilities to trigger."),
|
||||
noCreatureDyingTriggers ("Creatures dying don't cause abilities to trigger."),
|
||||
noNight ("It can't become night."),
|
||||
/* onlyOneAttackerATurn ("No more than one creature can attack each turn."), */
|
||||
onlyOneAttackerACombat ("No more than one creature can attack each combat."),
|
||||
|
||||
@@ -31,6 +31,7 @@ public enum AbilityKey {
|
||||
CastSA("CastSA"),
|
||||
Card("Card"),
|
||||
Cards("Cards"),
|
||||
CardsFiltered("CardsFiltered"),
|
||||
CardLKI("CardLKI"),
|
||||
Cause("Cause"),
|
||||
Causer("Causer"),
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package forge.game.staticability;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Table.Cell;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.*;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class StaticAbilityDisableTriggers {
|
||||
|
||||
static String MODE = "DisableTriggers";
|
||||
|
||||
public static boolean disabled(final Game game, final Trigger regtrig, final Map<AbilityKey, Object> runParams) {
|
||||
CardCollectionView cardList = null;
|
||||
// if LTB look back
|
||||
if ((regtrig.getMode() == TriggerType.ChangesZone || regtrig.getMode() == TriggerType.ChangesZoneAll) && "Battlefield".equals(regtrig.getParam("Origin"))) {
|
||||
if (runParams.containsKey(AbilityKey.LastStateBattlefield)) {
|
||||
cardList = (CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield);
|
||||
}
|
||||
if (cardList == null) {
|
||||
cardList = game.getLastStateBattlefield();
|
||||
}
|
||||
} else {
|
||||
cardList = game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES);
|
||||
}
|
||||
|
||||
for (final Card ca : cardList) {
|
||||
for (final StaticAbility stAb : ca.getStaticAbilities()) {
|
||||
if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isDisabled(stAb, regtrig, runParams)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isDisabled(final StaticAbility stAb, final Trigger regtrig, final Map<AbilityKey, Object> runParams) {
|
||||
final TriggerType trigMode = regtrig.getMode();
|
||||
|
||||
// CR 603.2e
|
||||
if (stAb.hasParam("ValidCard") && regtrig.getSpawningAbility() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!stAb.matchesValidParam("ValidCard", regtrig.getHostCard())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stAb.hasParam("ValidMode")) {
|
||||
if (!ArrayUtils.contains(stAb.getParam("ValidMode").split(","), trigMode.toString())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (trigMode.equals(TriggerType.ChangesZone)) {
|
||||
// Cause of the trigger – the card changing zones
|
||||
if (!stAb.matchesValidParam("ValidCause", runParams.get(AbilityKey.Card))) {
|
||||
return false;
|
||||
}
|
||||
if (!stAb.matchesValidParam("Destination", runParams.get(AbilityKey.Destination))) {
|
||||
return false;
|
||||
}
|
||||
if (!stAb.matchesValidParam("Origin", runParams.get(AbilityKey.Origin))) {
|
||||
return false;
|
||||
}
|
||||
if ("Graveyard".equals(runParams.get(AbilityKey.Destination))
|
||||
&& "Battlefield".equals(runParams.get(AbilityKey.Origin))) {
|
||||
// Allow triggered ability of a dying creature that triggers
|
||||
// only when that creature is put into a graveyard from anywhere
|
||||
if ("Card.Self".equals(regtrig.getParam("ValidCard"))
|
||||
&& (!regtrig.hasParam("Origin") || "Any".equals(regtrig.getParam("Origin")))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (trigMode.equals(TriggerType.ChangesZoneAll)) {
|
||||
final String origin = stAb.getParam("Origin");
|
||||
final String destination = stAb.getParam("Destination");
|
||||
// check if some causes were already ignored by a different ability, then the forbidden causes will be combined
|
||||
CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.CardsFiltered);
|
||||
if (table == null) {
|
||||
table = (CardZoneTable) runParams.get(AbilityKey.Cards);
|
||||
}
|
||||
CardZoneTable filtered = new CardZoneTable();
|
||||
boolean possiblyDisabled = false;
|
||||
|
||||
// purge all forbidden causes from table
|
||||
for (Cell<ZoneType, ZoneType, CardCollection> cell : table.cellSet()) {
|
||||
CardCollection changers = cell.getValue();
|
||||
if ((origin == null || cell.getRowKey() == ZoneType.valueOf(origin)) &&
|
||||
(destination == null || cell.getColumnKey() == ZoneType.valueOf(destination))) {
|
||||
changers = CardLists.filter(changers, Predicates.not(CardPredicates.restriction(stAb.getParam("ValidCause").split(","), stAb.getHostCard().getController(), stAb.getHostCard(), stAb)));
|
||||
// static will match some of the causes
|
||||
if (changers.size() < cell.getValue().size()) {
|
||||
possiblyDisabled = true;
|
||||
}
|
||||
}
|
||||
filtered.put(cell.getRowKey(), cell.getColumnKey(), changers);
|
||||
}
|
||||
|
||||
if (!possiblyDisabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// test if trigger would still fire when ignoring forbidden causes
|
||||
final Map<AbilityKey, Object> runParamsFiltered = AbilityKey.newMap(runParams);
|
||||
runParamsFiltered.put(AbilityKey.Cards, filtered);
|
||||
if (regtrig.performTest(runParamsFiltered)) {
|
||||
// store the filtered Cards because Panharmonicon shouldn't see the others
|
||||
runParams.put(AbilityKey.CardsFiltered, filtered);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public class StaticAbilityPanharmonicon {
|
||||
|
||||
CardCollectionView cardList = null;
|
||||
// if LTB look back
|
||||
if (t.getMode() == TriggerType.ChangesZone && "Battlefield".equals(t.getParam("Origin"))) {
|
||||
if ((t.getMode() == TriggerType.ChangesZone || t.getMode() == TriggerType.ChangesZoneAll) && "Battlefield".equals(t.getParam("Origin"))) {
|
||||
if (runParams.containsKey(AbilityKey.LastStateBattlefield)) {
|
||||
cardList = (CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield);
|
||||
}
|
||||
@@ -102,7 +102,11 @@ public class StaticAbilityPanharmonicon {
|
||||
// Check if the cards have a trigger at all
|
||||
final String origin = stAb.getParam("Origin");
|
||||
final String destination = stAb.getParam("Destination");
|
||||
final CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards);
|
||||
// check if some causes were ignored
|
||||
CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.CardsFiltered);
|
||||
if (table == null) {
|
||||
table = (CardZoneTable) runParams.get(AbilityKey.Cards);
|
||||
}
|
||||
|
||||
if (table.filterCards(origin == null ? null : ImmutableList.of(ZoneType.smartValueOf(origin)), ZoneType.smartValueOf(destination), stAb.getParam("ValidCause"), card, stAb).isEmpty()) {
|
||||
return false;
|
||||
|
||||
@@ -83,7 +83,7 @@ public class TriggerAbilityTriggered extends Trigger {
|
||||
if (!matchesValidParam("ValidCause", causes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (hasParam("TriggeredOwnAbility") && "True".equals(getParam("TriggeredOwnAbility")) && !Iterables.contains(causes, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,15 @@ package forge.game.trigger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Table.Cell;
|
||||
|
||||
import forge.game.CardTraitBase;
|
||||
import forge.game.CardTraitPredicates;
|
||||
import forge.game.Game;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.IHasSVars;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityKey;
|
||||
@@ -39,6 +36,7 @@ import forge.game.card.*;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbilityDisableTriggers;
|
||||
import forge.game.staticability.StaticAbilityPanharmonicon;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -445,74 +443,9 @@ public class TriggerHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Torpor Orb check
|
||||
if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers)
|
||||
&& !regtrig.isStatic()) {
|
||||
if (mode.equals(TriggerType.ChangesZone)) {
|
||||
if (runParams.get(AbilityKey.Destination) instanceof String) {
|
||||
final String dest = (String) runParams.get(AbilityKey.Destination);
|
||||
if (dest.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) {
|
||||
final Card card = (Card) runParams.get(AbilityKey.Card);
|
||||
if (card.isCreature()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mode.equals(TriggerType.ChangesZoneAll)) {
|
||||
CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards);
|
||||
// find out if any other cards would still trigger it
|
||||
boolean found = false;
|
||||
for (Cell<ZoneType, ZoneType, CardCollection> cell : table.cellSet()) {
|
||||
// this currently assumes the table will not contain multiple destinations
|
||||
// however with some effects (e.g. Goblin Welder) that should indeed be the case
|
||||
// once Forge handles that correctly this section needs to account for that
|
||||
// (by doing a closer check of the triggered ability first)
|
||||
if (cell.getColumnKey() != ZoneType.Battlefield) {
|
||||
found = true;
|
||||
} else if (Iterables.any(cell.getValue(), Predicates.not(CardPredicates.isType("Creature")))) {
|
||||
found = true;
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // Torpor Orb check
|
||||
|
||||
if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureDyingTriggers)
|
||||
&& !regtrig.isStatic()) {
|
||||
if (mode.equals(TriggerType.ChangesZone)) {
|
||||
if (runParams.get(AbilityKey.Destination) instanceof String && runParams.get(AbilityKey.Origin) instanceof String) {
|
||||
final String dest = (String) runParams.get(AbilityKey.Destination);
|
||||
final String origin = (String) runParams.get(AbilityKey.Origin);
|
||||
if (dest.equals("Graveyard") && origin.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) {
|
||||
// It will trigger if the ability is of a dying creature that triggers only when that creature is put into a graveyard from anywhere
|
||||
if (!"Card.Self".equals(regtrig.getParam("ValidCard")) || (regtrig.hasParam("Origin") && !"Any".equals(regtrig.getParam("Origin")))) {
|
||||
final Card card = (Card) runParams.get(AbilityKey.Card);
|
||||
if (card.isCreature()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mode.equals(TriggerType.ChangesZoneAll)) {
|
||||
CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards);
|
||||
boolean found = false;
|
||||
for (Cell<ZoneType, ZoneType, CardCollection> cell : table.cellSet()) {
|
||||
if (cell.getRowKey() != ZoneType.Battlefield) {
|
||||
found = true;
|
||||
} else if (cell.getColumnKey() != ZoneType.Graveyard) {
|
||||
found = true;
|
||||
} else if (Iterables.any(cell.getValue(), Predicates.not(CardPredicates.isType("Creature")))) {
|
||||
found = true;
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// check if any static abilities are disabling the trigger (Torpor Orb and the like)
|
||||
if (!regtrig.isStatic() && StaticAbilityDisableTriggers.disabled(game, regtrig, runParams)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user