Merge branch 'new-cards' into 'master'

Strict Proctor

See merge request core-developers/forge!4393
This commit is contained in:
Michael Kamensky
2021-04-06 07:27:15 +00:00
6 changed files with 151 additions and 4 deletions

View File

@@ -75,6 +75,7 @@ public enum AbilityKey {
LifeGained("LifeGained"),
Mana("Mana"),
MergedCards("MergedCards"),
Mode("Mode"),
MonstrosityAmount("MonstrosityAmount"),
NewCard("NewCard"),
NewCounterAmount("NewCounterAmount"),
@@ -118,6 +119,7 @@ public enum AbilityKey {
Token("Token"),
TokenNum("TokenNum"),
Transformer("Transformer"),
TriggeredParams("TriggeredParams"),
Vehicle("Vehicle"),
Won("Won");

View File

@@ -0,0 +1,131 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.game.trigger;
import com.google.common.collect.ImmutableList;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.card.Card;
import forge.game.card.CardZoneTable;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.Localizer;
import java.util.*;
/**
* <p>
* TriggerAbilityTriggered class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class TriggerAbilityTriggered extends Trigger {
public TriggerAbilityTriggered(final Map<String, String> params, final Card host, final boolean intrinsic) {
super(params, host, intrinsic);
}
/** {@inheritDoc}
* @param runParams*/
@Override
public final boolean performTest(final Map<AbilityKey, Object> runParams) {
final SpellAbility spellAbility = (SpellAbility) runParams.get(AbilityKey.SpellAbility);
if (spellAbility == null) {
System.out.println("TriggerAbilityTriggered performTest encountered spellAbility == null. runParams2 = " + runParams);
return false;
}
final Card source = spellAbility.getHostCard();
final Iterable<Card> causes = (Iterable<Card>) runParams.get(AbilityKey.Cause);
final Game game = source.getGame();
if (hasParam("ValidMode")) {
List<String> validModes = Arrays.asList(getParam("ValidMode").split(","));
String mode = (String) runParams.get(AbilityKey.Mode);
if (!validModes.contains(mode)) {
return false;
}
}
if (hasParam("ValidDestination")) {
List<String> validDestinations = Arrays.asList(getParam("ValidDestination").split(","));
List<String> destinations = Arrays.asList(((String)runParams.get(AbilityKey.Destination)).split(","));
if (Collections.disjoint(validDestinations, destinations)) {
return false;
}
}
if (!matchesValidParam("ValidSource", source)) {
return false;
}
if (hasParam("ValidCause")) {
boolean match = false;
for (Card cause : causes) {
if(matchesValidParam("ValidCause", cause)) {
match = true;
}
}
if (!match) {
return false;
}
}
return true;
}
/** {@inheritDoc} */
@Override
public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Object> runParams) {
final SpellAbility triggeredSA = (SpellAbility) runParams.get(AbilityKey.SpellAbility);
sa.setTriggeringObject(AbilityKey.Source, triggeredSA.getHostCard());
sa.setTriggeringObjectsFrom(
runParams,
AbilityKey.SpellAbility,
AbilityKey.Cause);
}
@Override
public String getImportantStackObjects(SpellAbility sa) {
StringBuilder sb = new StringBuilder();
sb.append(Localizer.getInstance().getMessage("lblSpellAbility")).append(": ").append(sa.getTriggeringObject(AbilityKey.SpellAbility));
return sb.toString();
}
public static void addTriggeringObject(Trigger regtrig, SpellAbility sa, Map<AbilityKey, Object> runParams) {
Map<AbilityKey, Object> newRunParams = AbilityKey.newMap();
newRunParams.put(AbilityKey.Mode, regtrig.getMode().toString());
if (regtrig.getMode() == TriggerType.ChangesZone) {
newRunParams.put(AbilityKey.Destination, runParams.get(AbilityKey.Destination));
newRunParams.put(AbilityKey.Cause, ImmutableList.of(runParams.get(AbilityKey.Card)));
} else if (regtrig.getMode() == TriggerType.ChangesZoneAll) {
final CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards);
Set<String> destinations = new HashSet<>();
for (ZoneType dest : ZoneType.values()) {
if (table.containsColumn(dest) && !table.column(dest).isEmpty()) {
destinations.add(dest.toString());
}
}
newRunParams.put(AbilityKey.Destination, String.join(",", destinations));
newRunParams.put(AbilityKey.Cause, table.allCards());
}
sa.setTriggeringObject(AbilityKey.TriggeredParams, newRunParams);
}
}

View File

@@ -17,10 +17,7 @@
*/
package forge.game.trigger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
@@ -557,6 +554,7 @@ public class TriggerHandler {
sa.setTrigger(regtrig);
sa.setSourceTrigger(regtrig.getId());
regtrig.setTriggeringObjects(sa, runParams);
TriggerAbilityTriggered.addTriggeringObject(regtrig, sa, runParams);
sa.setTriggerRemembered(regtrig.getTriggerRemembered());
if (regtrig.hasParam("TriggerController")) {

View File

@@ -14,6 +14,7 @@ import forge.game.card.Card;
public enum TriggerType {
Abandoned(TriggerAbandoned.class),
AbilityCast(TriggerSpellAbilityCastOrCopy.class),
AbilityTriggered(TriggerAbilityTriggered.class),
Adapt(TriggerAdapt.class),
Always(TriggerAlways.class),
Attached(TriggerAttached.class),

View File

@@ -332,6 +332,13 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
runParams.put(AbilityKey.Crew, sp.getPaidList("TappedCards"));
game.getTriggerHandler().runTrigger(TriggerType.Crewed, runParams, false);
}
// Run AbilityTriggered
if (sp.isTrigger()) {
Map<AbilityKey, Object> newRunParams = (Map<AbilityKey, Object>) sp.getTriggeringObject(AbilityKey.TriggeredParams);
newRunParams.put(AbilityKey.SpellAbility, sp);
game.getTriggerHandler().runTrigger(TriggerType.AbilityTriggered, newRunParams, false);
}
} else {
// Run Copy triggers
if (sp.isSpell()) {

View File

@@ -0,0 +1,8 @@
Name:Strict Proctor
ManaCost:1 W
Types:Creature Spirit Cleric
PT:1/3
K:Flying
T:Mode$ AbilityTriggered | ValidDestination$ Battlefield | ValidMode$ ChangesZone,ChangesZoneAll | TriggerZones$ Battlefield | Execute$ TrigCounter | TriggerDescription$ Whenever a permanent entering the battlefield causes a triggered ability to trigger, counter that ability unless its controller pays {2}.
SVar:TrigCounter:DB$ Counter | Defined$ TriggeredSpellAbility | UnlessCost$ 2 | UnlessPayer$ TriggeredSpellAbilityController
Oracle:Flying\nWhenever a permanent entering the battlefield causes a triggered ability to trigger, counter that ability unless its controller pays {2}.