mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Trigger & Replacement: ensure abilities
This commit is contained in:
@@ -23,7 +23,6 @@ import com.google.common.collect.Lists;
|
|||||||
import forge.ai.ability.AnimateAi;
|
import forge.ai.ability.AnimateAi;
|
||||||
import forge.card.CardTypeView;
|
import forge.card.CardTypeView;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.ProtectEffect;
|
import forge.game.ability.effects.ProtectEffect;
|
||||||
@@ -196,12 +195,12 @@ public class AiAttackController {
|
|||||||
for (Card c : ai.getOpponents().getCardsIn(ZoneType.Battlefield)) {
|
for (Card c : ai.getOpponents().getCardsIn(ZoneType.Battlefield)) {
|
||||||
for (Trigger t : c.getTriggers()) {
|
for (Trigger t : c.getTriggers()) {
|
||||||
if (t.getMode() == TriggerType.Attacks) {
|
if (t.getMode() == TriggerType.Attacks) {
|
||||||
SpellAbility sa = t.getOverridingAbility();
|
SpellAbility sa = t.ensureAbility();
|
||||||
if (sa == null && t.hasParam("Execute")) {
|
if (sa == null) {
|
||||||
sa = AbilityFactory.getAbility(c, t.getParam("Execute"));
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sa != null && sa.getApi() == ApiType.EachDamage && "TriggeredAttacker".equals(sa.getParam("DefinedPlayers"))) {
|
if (sa.getApi() == ApiType.EachDamage && "TriggeredAttacker".equals(sa.getParam("DefinedPlayers"))) {
|
||||||
List<Card> valid = CardLists.getValidCards(c.getController().getCreaturesInPlay(), sa.getParam("ValidCards"), c.getController(), c, sa);
|
List<Card> valid = CardLists.getValidCards(c.getController().getCreaturesInPlay(), sa.getParam("ValidCards"), c.getController(), c, sa);
|
||||||
// TODO: this assumes that 1 damage is dealt per creature. Improve this to check the parameter/X to determine
|
// TODO: this assumes that 1 damage is dealt per creature. Improve this to check the parameter/X to determine
|
||||||
// how much damage is dealt by each of the creatures in the valid list.
|
// how much damage is dealt by each of the creatures in the valid list.
|
||||||
@@ -1349,9 +1348,9 @@ public class AiAttackController {
|
|||||||
if (!TriggerType.Exerted.equals(t.getMode())) {
|
if (!TriggerType.Exerted.equals(t.getMode())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SpellAbility sa = t.getOverridingAbility();
|
SpellAbility sa = t.ensureAbility();
|
||||||
if (sa == null) {
|
if (sa == null) {
|
||||||
sa = AbilityFactory.getAbility(c, t.getParam("Execute"));
|
continue;
|
||||||
}
|
}
|
||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
sa.setActivatingPlayer(c.getController());
|
sa.setActivatingPlayer(c.getController());
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import forge.card.ColorSet;
|
|||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.game.*;
|
import forge.game.*;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
@@ -1468,15 +1467,13 @@ public class ComputerUtil {
|
|||||||
// Triggered abilities
|
// Triggered abilities
|
||||||
if (c.isCreature() && c.isInZone(ZoneType.Battlefield) && CombatUtil.canAttack(c)) {
|
if (c.isCreature() && c.isInZone(ZoneType.Battlefield) && CombatUtil.canAttack(c)) {
|
||||||
for (final Trigger t : c.getTriggers()) {
|
for (final Trigger t : c.getTriggers()) {
|
||||||
if ("Attacks".equals(t.getParam("Mode")) && t.hasParam("Execute")) {
|
if (TriggerType.Attacks.equals(t.getMode())) {
|
||||||
String exec = c.getSVar(t.getParam("Execute"));
|
SpellAbility sa = t.ensureAbility();
|
||||||
if (!exec.isEmpty()) {
|
if (sa == null) {
|
||||||
SpellAbility trigSa = AbilityFactory.getAbility(exec, c);
|
continue;
|
||||||
if (trigSa != null && trigSa.getApi() == ApiType.LoseLife
|
}
|
||||||
&& trigSa.getParamOrDefault("Defined", "").contains("Opponent")) {
|
if (sa.getApi() == ApiType.LoseLife && sa.getParamOrDefault("Defined", "").contains("Opponent")) {
|
||||||
trigSa.setHostCard(c);
|
damage += AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("LifeAmount"), sa);
|
||||||
damage += AbilityUtils.calculateAmount(trigSa.getHostCard(), trigSa.getParam("LifeAmount"), trigSa);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2612,7 +2609,6 @@ public class ComputerUtil {
|
|||||||
theTriggers.addAll(c.getTriggers());
|
theTriggers.addAll(c.getTriggers());
|
||||||
}
|
}
|
||||||
for (Trigger trigger : theTriggers) {
|
for (Trigger trigger : theTriggers) {
|
||||||
Map<String, String> trigParams = trigger.getMapParams();
|
|
||||||
final Card source = trigger.getHostCard();
|
final Card source = trigger.getHostCard();
|
||||||
|
|
||||||
|
|
||||||
@@ -2622,73 +2618,43 @@ public class ComputerUtil {
|
|||||||
if (!trigger.requirementsCheck(game)) {
|
if (!trigger.requirementsCheck(game)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TriggerType mode = trigger.getMode();
|
if (trigger.getMode() != TriggerType.SpellCast) {
|
||||||
if (mode != TriggerType.SpellCast) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trigParams.containsKey("ValidCard")) {
|
if (trigger.hasParam("ValidCard")) {
|
||||||
if (!card.isValid(trigParams.get("ValidCard"), source.getController(), source, sa)) {
|
if (!card.isValid(trigger.getParam("ValidCard"), source.getController(), source, sa)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trigParams.containsKey("ValidActivatingPlayer")) {
|
if (trigger.hasParam("ValidActivatingPlayer")) {
|
||||||
if (!player.isValid(trigParams.get("ValidActivatingPlayer"), source.getController(), source, sa)) {
|
if (!player.isValid(trigger.getParam("ValidActivatingPlayer"), source.getController(), source, sa)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trigParams.containsKey("Execute")) {
|
// fall back for OverridingAbility
|
||||||
// fall back for OverridingAbility
|
SpellAbility trigSa = trigger.ensureAbility();
|
||||||
SpellAbility trigSa = trigger.getOverridingAbility();
|
if (trigSa == null) {
|
||||||
if (trigSa == null) {
|
continue;
|
||||||
|
}
|
||||||
|
if (trigSa.getApi() == ApiType.DealDamage) {
|
||||||
|
if (!"TriggeredActivator".equals(trigSa.getParam("Defined"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trigSa.getApi() == ApiType.DealDamage) {
|
if (!trigSa.hasParam("NumDmg")) {
|
||||||
if (!"TriggeredActivator".equals(trigSa.getParam("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!trigSa.hasParam("NumDmg")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += ComputerUtilCombat.predictDamageTo(player,
|
|
||||||
AbilityUtils.calculateAmount(source, trigSa.getParam("NumDmg"), trigSa), source, false);
|
|
||||||
} else if (trigSa.getApi() == ApiType.LoseLife) {
|
|
||||||
if (!"TriggeredActivator".equals(trigSa.getParam("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!trigSa.hasParam("LifeAmount")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += AbilityUtils.calculateAmount(source, trigSa.getParam("LifeAmount"), trigSa);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String ability = source.getSVar(trigParams.get("Execute"));
|
|
||||||
if (ability.isEmpty()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
damage += ComputerUtilCombat.predictDamageTo(player,
|
||||||
final Map<String, String> abilityParams = AbilityFactory.getMapParams(ability);
|
AbilityUtils.calculateAmount(source, trigSa.getParam("NumDmg"), trigSa), source, false);
|
||||||
if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("DealDamage"))
|
} else if (trigSa.getApi() == ApiType.LoseLife) {
|
||||||
|| (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("DealDamage"))) {
|
if (!"TriggeredActivator".equals(trigSa.getParam("Defined"))) {
|
||||||
if (!"TriggeredActivator".equals(abilityParams.get("Defined"))) {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!abilityParams.containsKey("NumDmg")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += ComputerUtilCombat.predictDamageTo(player,
|
|
||||||
AbilityUtils.calculateAmount(source, abilityParams.get("NumDmg"), null), source, false);
|
|
||||||
} else if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("LoseLife"))
|
|
||||||
|| (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("LoseLife"))) {
|
|
||||||
if (!"TriggeredActivator".equals(abilityParams.get("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!abilityParams.containsKey("LifeAmount")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += AbilityUtils.calculateAmount(source, abilityParams.get("LifeAmount"), null);
|
|
||||||
}
|
}
|
||||||
|
if (!trigSa.hasParam("LifeAmount")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
damage += AbilityUtils.calculateAmount(source, trigSa.getParam("LifeAmount"), trigSa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2704,7 +2670,6 @@ public class ComputerUtil {
|
|||||||
theTriggers.addAll(card.getTriggers());
|
theTriggers.addAll(card.getTriggers());
|
||||||
}
|
}
|
||||||
for (Trigger trigger : theTriggers) {
|
for (Trigger trigger : theTriggers) {
|
||||||
Map<String, String> trigParams = trigger.getMapParams();
|
|
||||||
final Card source = trigger.getHostCard();
|
final Card source = trigger.getHostCard();
|
||||||
|
|
||||||
|
|
||||||
@@ -2714,74 +2679,43 @@ public class ComputerUtil {
|
|||||||
if (!trigger.requirementsCheck(game)) {
|
if (!trigger.requirementsCheck(game)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trigParams.containsKey("CheckOnTriggeredCard")
|
if (trigger.hasParam("CheckOnTriggeredCard")
|
||||||
&& AbilityUtils.getDefinedCards(permanent, source.getSVar(trigParams.get("CheckOnTriggeredCard").split(" ")[0]), null).isEmpty()) {
|
&& AbilityUtils.getDefinedCards(permanent, source.getSVar(trigger.getParam("CheckOnTriggeredCard").split(" ")[0]), null).isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TriggerType mode = trigger.getMode();
|
if (trigger.getMode() != TriggerType.ChangesZone) {
|
||||||
if (mode != TriggerType.ChangesZone) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!"Battlefield".equals(trigParams.get("Destination"))) {
|
if (!"Battlefield".equals(trigger.getParam("Destination"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trigParams.containsKey("ValidCard")) {
|
if (trigger.hasParam("ValidCard")) {
|
||||||
if (!permanent.isValid(trigParams.get("ValidCard"), source.getController(), source, null)) {
|
if (!permanent.isValid(trigger.getParam("ValidCard"), source.getController(), source, null)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!trigParams.containsKey("Execute")) {
|
// fall back for OverridingAbility
|
||||||
// fall back for OverridingAbility
|
SpellAbility trigSa = trigger.ensureAbility();
|
||||||
SpellAbility trigSa = trigger.getOverridingAbility();
|
if (trigSa == null) {
|
||||||
if (trigSa == null) {
|
continue;
|
||||||
|
}
|
||||||
|
if (trigSa.getApi() == ApiType.DealDamage) {
|
||||||
|
if (!"TriggeredCardController".equals(trigSa.getParam("Defined"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trigSa.getApi() == ApiType.DealDamage) {
|
if (!trigSa.hasParam("NumDmg")) {
|
||||||
if (!"TriggeredCardController".equals(trigSa.getParam("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!trigSa.hasParam("NumDmg")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += ComputerUtilCombat.predictDamageTo(player,
|
|
||||||
AbilityUtils.calculateAmount(source, trigSa.getParam("NumDmg"), trigSa), source, false);
|
|
||||||
} else if (trigSa.getApi() == ApiType.LoseLife) {
|
|
||||||
if (!"TriggeredCardController".equals(trigSa.getParam("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!trigSa.hasParam("LifeAmount")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += AbilityUtils.calculateAmount(source, trigSa.getParam("LifeAmount"), trigSa);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String ability = source.getSVar(trigParams.get("Execute"));
|
|
||||||
if (ability.isEmpty()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
damage += ComputerUtilCombat.predictDamageTo(player,
|
||||||
final Map<String, String> abilityParams = AbilityFactory.getMapParams(ability);
|
AbilityUtils.calculateAmount(source, trigSa.getParam("NumDmg"), trigSa), source, false);
|
||||||
// Destroy triggers
|
} else if (trigSa.getApi() == ApiType.LoseLife) {
|
||||||
if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("DealDamage"))
|
if (!"TriggeredCardController".equals(trigSa.getParam("Defined"))) {
|
||||||
|| (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("DealDamage"))) {
|
continue;
|
||||||
if (!"TriggeredCardController".equals(abilityParams.get("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!abilityParams.containsKey("NumDmg")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += ComputerUtilCombat.predictDamageTo(player,
|
|
||||||
AbilityUtils.calculateAmount(source, abilityParams.get("NumDmg"), null), source, false);
|
|
||||||
} else if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("LoseLife"))
|
|
||||||
|| (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("LoseLife"))) {
|
|
||||||
if (!"TriggeredCardController".equals(abilityParams.get("Defined"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!abilityParams.containsKey("LifeAmount")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
damage += AbilityUtils.calculateAmount(source, abilityParams.get("LifeAmount"), null);
|
|
||||||
}
|
}
|
||||||
|
if (!trigSa.hasParam("LifeAmount")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
damage += AbilityUtils.calculateAmount(source, trigSa.getParam("LifeAmount"), trigSa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return damage;
|
return damage;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import forge.deck.Deck;
|
|||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
@@ -697,39 +696,21 @@ public class ComputerUtilCard {
|
|||||||
}
|
}
|
||||||
// same for Trigger that does make Tokens
|
// same for Trigger that does make Tokens
|
||||||
for(Trigger t:c.getTriggers()){
|
for(Trigger t:c.getTriggers()){
|
||||||
SpellAbility sa = t.getOverridingAbility();
|
SpellAbility sa = t.ensureAbility();
|
||||||
String sTokenTypes = null;
|
|
||||||
if (sa != null) {
|
if (sa != null) {
|
||||||
if (sa.getApi() != ApiType.Token || !sa.hasParam("TokenTypes")) {
|
if (sa.getApi() != ApiType.Token || !sa.hasParam("TokenTypes")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sTokenTypes = sa.getParam("TokenTypes");
|
for (String var : sa.getParam("TokenTypes").split(",")) {
|
||||||
} else if (t.hasParam("Execute")) {
|
if (!CardType.isACreatureType(var)) {
|
||||||
String name = t.getParam("Execute");
|
continue;
|
||||||
if (!c.hasSVar(name)) {
|
}
|
||||||
continue;
|
Integer count = typesInDeck.get(var);
|
||||||
|
if (count == null) {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
typesInDeck.put(var, count + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> params = AbilityFactory.getMapParams(c.getSVar(name));
|
|
||||||
if (!params.containsKey("TokenTypes")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sTokenTypes = params.get("TokenTypes");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sTokenTypes == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String var : sTokenTypes.split(",")) {
|
|
||||||
if (!CardType.isACreatureType(var)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Integer count = typesInDeck.get(var);
|
|
||||||
if (count == null) {
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
typesInDeck.put(var, count + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// special rule for Fabricate and Servo
|
// special rule for Fabricate and Servo
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import com.google.common.collect.Maps;
|
|||||||
import forge.game.CardTraitBase;
|
import forge.game.CardTraitBase;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
@@ -46,7 +45,6 @@ import forge.game.replacement.ReplacementType;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.TriggerHandler;
|
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
@@ -1274,44 +1272,26 @@ public class ComputerUtilCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final Trigger trigger : theTriggers) {
|
for (final Trigger trigger : theTriggers) {
|
||||||
final Map<String, String> trigParams = trigger.getMapParams();
|
|
||||||
final Card source = trigger.getHostCard();
|
final Card source = trigger.getHostCard();
|
||||||
|
|
||||||
if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, combat)) {
|
if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, combat)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> abilityParams = null;
|
SpellAbility sa = trigger.ensureAbility();
|
||||||
if (trigger.getOverridingAbility() != null) {
|
if (sa == null) {
|
||||||
abilityParams = trigger.getOverridingAbility().getMapParams();
|
|
||||||
} else if (trigParams.containsKey("Execute")) {
|
|
||||||
final String ability = source.getSVar(trigParams.get("Execute"));
|
|
||||||
abilityParams = AbilityFactory.getMapParams(ability);
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abilityParams.containsKey("ValidTgts") || abilityParams.containsKey("Tgt")) {
|
if (sa.usesTargeting()) {
|
||||||
continue; // targeted pumping not supported
|
continue; // targeted pumping not supported
|
||||||
}
|
}
|
||||||
if (abilityParams.containsKey("AB") && !abilityParams.get("AB").equals("Pump")
|
|
||||||
&& !abilityParams.get("AB").equals("PumpAll")) {
|
if (!ApiType.Pump.equals(sa.getApi()) && !ApiType.PumpAll.equals(sa.getApi())) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (abilityParams.containsKey("DB") && !abilityParams.get("DB").equals("Pump")
|
|
||||||
&& !abilityParams.get("DB").equals("PumpAll")) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abilityParams.containsKey("Cost")) {
|
if (sa.hasParam("Cost")) {
|
||||||
SpellAbility sa = null;
|
|
||||||
if (trigger.getOverridingAbility() != null) {
|
|
||||||
sa = trigger.getOverridingAbility();
|
|
||||||
} else {
|
|
||||||
final String ability = source.getSVar(trigParams.get("Execute"));
|
|
||||||
sa = AbilityFactory.getAbility(ability, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
sa.setActivatingPlayer(source.getController());
|
sa.setActivatingPlayer(source.getController());
|
||||||
if (!CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa)) {
|
if (!CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1319,15 +1299,15 @@ public class ComputerUtilCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Card> list = Lists.newArrayList();
|
List<Card> list = Lists.newArrayList();
|
||||||
if (!abilityParams.containsKey("ValidCards")) {
|
if (!sa.hasParam("ValidCards")) {
|
||||||
list = AbilityUtils.getDefinedCards(source, abilityParams.get("Defined"), null);
|
list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), null);
|
||||||
}
|
}
|
||||||
if (abilityParams.containsKey("Defined") && abilityParams.get("Defined").equals("TriggeredAttacker")) {
|
if (sa.hasParam("Defined") && sa.getParam("Defined").equals("TriggeredAttacker")) {
|
||||||
list.add(attacker);
|
list.add(attacker);
|
||||||
}
|
}
|
||||||
if (abilityParams.containsKey("ValidCards")) {
|
if (sa.hasParam("ValidCards")) {
|
||||||
if (attacker.isValid(abilityParams.get("ValidCards").split(","), source.getController(), source, null)
|
if (attacker.isValid(sa.getParam("ValidCards").split(","), source.getController(), source, null)
|
||||||
|| attacker.isValid(abilityParams.get("ValidCards").replace("attacking+", "").split(","),
|
|| attacker.isValid(sa.getParam("ValidCards").replace("attacking+", "").split(","),
|
||||||
source.getController(), source, null)) {
|
source.getController(), source, null)) {
|
||||||
list.add(attacker);
|
list.add(attacker);
|
||||||
}
|
}
|
||||||
@@ -1338,11 +1318,11 @@ public class ComputerUtilCombat {
|
|||||||
if (!list.contains(attacker)) {
|
if (!list.contains(attacker)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!abilityParams.containsKey("NumAtt")) {
|
if (!sa.hasParam("NumAtt")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String att = abilityParams.get("NumAtt");
|
String att = sa.getParam("NumAtt");
|
||||||
if (att.startsWith("+")) {
|
if (att.startsWith("+")) {
|
||||||
att = att.substring(1);
|
att = att.substring(1);
|
||||||
}
|
}
|
||||||
@@ -1657,35 +1637,26 @@ public class ComputerUtilCombat {
|
|||||||
theTriggers.addAll(card.getTriggers());
|
theTriggers.addAll(card.getTriggers());
|
||||||
}
|
}
|
||||||
for (Trigger trigger : theTriggers) {
|
for (Trigger trigger : theTriggers) {
|
||||||
Map<String, String> trigParams = trigger.getMapParams();
|
|
||||||
final Card source = trigger.getHostCard();
|
final Card source = trigger.getHostCard();
|
||||||
|
|
||||||
if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, null)) {
|
if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, null)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//consider delayed triggers
|
SpellAbility sa = trigger.ensureAbility();
|
||||||
if (trigParams.containsKey("DelayedTrigger")) {
|
if (sa == null) {
|
||||||
String sVarName = trigParams.get("DelayedTrigger");
|
|
||||||
trigger = TriggerHandler.parseTrigger(source.getSVar(sVarName), trigger.getHostCard(), true);
|
|
||||||
trigParams = trigger.getMapParams();
|
|
||||||
}
|
|
||||||
if (!trigParams.containsKey("Execute")) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String ability = source.getSVar(trigParams.get("Execute"));
|
if (ApiType.Destroy.equals(sa.getApi())) {
|
||||||
final Map<String, String> abilityParams = AbilityFactory.getMapParams(ability);
|
if (!sa.hasParam("Defined")) {
|
||||||
if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("Destroy"))
|
|
||||||
|| (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("Destroy"))) {
|
|
||||||
if (!abilityParams.containsKey("Defined")) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (abilityParams.get("Defined").equals("TriggeredAttacker")) {
|
if (sa.getParam("Defined").equals("TriggeredAttacker")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (abilityParams.get("Defined").equals("Self") && source.equals(attacker)) {
|
if (sa.getParam("Defined").equals("Self") && source.equals(attacker)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (abilityParams.get("Defined").equals("TriggeredTarget") && source.equals(blocker)) {
|
if (sa.getParam("Defined").equals("TriggeredTarget") && source.equals(blocker)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1935,36 +1906,27 @@ public class ComputerUtilCombat {
|
|||||||
theTriggers.addAll(card.getTriggers());
|
theTriggers.addAll(card.getTriggers());
|
||||||
}
|
}
|
||||||
for (Trigger trigger : theTriggers) {
|
for (Trigger trigger : theTriggers) {
|
||||||
Map<String, String> trigParams = trigger.getMapParams();
|
|
||||||
final Card source = trigger.getHostCard();
|
final Card source = trigger.getHostCard();
|
||||||
|
|
||||||
if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, null)) {
|
if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, null)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//consider delayed triggers
|
SpellAbility sa = trigger.ensureAbility();
|
||||||
if (trigParams.containsKey("DelayedTrigger")) {
|
if (sa == null) {
|
||||||
String sVarName = trigParams.get("DelayedTrigger");
|
|
||||||
trigger = TriggerHandler.parseTrigger(source.getSVar(sVarName), trigger.getHostCard(), true);
|
|
||||||
trigParams = trigger.getMapParams();
|
|
||||||
}
|
|
||||||
if (!trigParams.containsKey("Execute")) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String ability = source.getSVar(trigParams.get("Execute"));
|
|
||||||
final Map<String, String> abilityParams = AbilityFactory.getMapParams(ability);
|
|
||||||
// Destroy triggers
|
// Destroy triggers
|
||||||
if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("Destroy"))
|
if (ApiType.Destroy.equals(sa.getApi())) {
|
||||||
|| (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("Destroy"))) {
|
if (!sa.hasParam("Defined")) {
|
||||||
if (!abilityParams.containsKey("Defined")) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (abilityParams.get("Defined").equals("TriggeredBlocker")) {
|
if (sa.getParam("Defined").equals("TriggeredBlocker")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (abilityParams.get("Defined").equals("Self") && source.equals(blocker)) {
|
if (sa.getParam("Defined").equals("Self") && source.equals(blocker)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (abilityParams.get("Defined").equals("TriggeredTarget") && source.equals(attacker)) {
|
if (sa.getParam("Defined").equals("TriggeredTarget") && source.equals(attacker)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2578,26 +2540,24 @@ public class ComputerUtilCombat {
|
|||||||
|
|
||||||
// Test for some special triggers that can change the creature in combat
|
// Test for some special triggers that can change the creature in combat
|
||||||
for (Trigger t : attacker.getTriggers()) {
|
for (Trigger t : attacker.getTriggers()) {
|
||||||
if (t.getMode() == TriggerType.Attacks && t.hasParam("Execute")) {
|
if (t.getMode() == TriggerType.Attacks) {
|
||||||
if (!attacker.hasSVar(t.getParam("Execute"))) {
|
SpellAbility exec = t.ensureAbility();
|
||||||
|
if (exec == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SpellAbility exec = AbilityFactory.getAbility(attacker, t.getParam("Execute"));
|
if (exec.getApi() == ApiType.Clone && "Self".equals(exec.getParam("CloneTarget"))
|
||||||
if (exec != null) {
|
&& exec.hasParam("ValidTgts") && exec.getParam("ValidTgts").contains("Creature")
|
||||||
if (exec.getApi() == ApiType.Clone && "Self".equals(exec.getParam("CloneTarget"))
|
&& exec.getParam("ValidTgts").contains("attacking")) {
|
||||||
&& exec.hasParam("ValidTgts") && exec.getParam("ValidTgts").contains("Creature")
|
// Tilonalli's Skinshifter and potentially other similar cards that can clone other stuff
|
||||||
&& exec.getParam("ValidTgts").contains("attacking")) {
|
// while attacking
|
||||||
// Tilonalli's Skinshifter and potentially other similar cards that can clone other stuff
|
if (exec.getParam("ValidTgts").contains("nonLegendary") && attacker.getType().isLegendary()) {
|
||||||
// while attacking
|
continue;
|
||||||
if (exec.getParam("ValidTgts").contains("nonLegendary") && attacker.getType().isLegendary()) {
|
}
|
||||||
continue;
|
int maxPwr = 0;
|
||||||
}
|
for (Card c : attacker.getController().getCreaturesInPlay()) {
|
||||||
int maxPwr = 0;
|
if (c.getNetPower() > maxPwr || (c.getNetPower() == maxPwr && ComputerUtilCard.evaluateCreature(c) > ComputerUtilCard.evaluateCreature(attackerAfterTrigs))) {
|
||||||
for (Card c : attacker.getController().getCreaturesInPlay()) {
|
maxPwr = c.getNetPower();
|
||||||
if (c.getNetPower() > maxPwr || (c.getNetPower() == maxPwr && ComputerUtilCard.evaluateCreature(c) > ComputerUtilCard.evaluateCreature(attackerAfterTrigs))) {
|
attackerAfterTrigs = c;
|
||||||
maxPwr = c.getNetPower();
|
|
||||||
attackerAfterTrigs = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import forge.card.MagicColor;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
@@ -636,10 +635,7 @@ public class SpecialCardAi {
|
|||||||
boolean canRetFromGrave = false;
|
boolean canRetFromGrave = false;
|
||||||
String name = c.getName().replace(',', ';');
|
String name = c.getName().replace(',', ';');
|
||||||
for (Trigger t : c.getTriggers()) {
|
for (Trigger t : c.getTriggers()) {
|
||||||
SpellAbility ab = null;
|
SpellAbility ab = t.ensureAbility();
|
||||||
if (t.hasParam("Execute")) {
|
|
||||||
ab = AbilityFactory.getAbility(c.getSVar(t.getParam("Execute")), c);
|
|
||||||
}
|
|
||||||
if (ab == null) { continue; }
|
if (ab == null) { continue; }
|
||||||
|
|
||||||
if (ab.getApi() == ApiType.ChangeZone
|
if (ab.getApi() == ApiType.ChangeZone
|
||||||
|
|||||||
@@ -1086,12 +1086,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
final Map<String, String> params = t.getMapParams();
|
final Map<String, String> params = t.getMapParams();
|
||||||
if ("Card.Self".equals(params.get("ValidCard"))
|
if ("Card.Self".equals(params.get("ValidCard"))
|
||||||
&& "Battlefield".equals(params.get("Destination"))) {
|
&& "Battlefield".equals(params.get("Destination"))) {
|
||||||
SpellAbility trigSa = null;
|
SpellAbility trigSa = t.ensureAbility();
|
||||||
if (t.hasParam("Execute") && attachSource.hasSVar(t.getParam("Execute"))) {
|
|
||||||
trigSa = AbilityFactory.getAbility(attachSource.getSVar(params.get("Execute")), attachSource);
|
|
||||||
} else if (t.getOverridingAbility() != null) {
|
|
||||||
trigSa = t.getOverridingAbility();
|
|
||||||
}
|
|
||||||
if (trigSa != null && trigSa.getApi() == ApiType.DealDamage && "Enchanted".equals(trigSa.getParam("Defined"))) {
|
if (trigSa != null && trigSa.getApi() == ApiType.DealDamage && "Enchanted".equals(trigSa.getParam("Defined"))) {
|
||||||
for (Card target : list) {
|
for (Card target : list) {
|
||||||
if (!target.getController().isOpponentOf(ai)) {
|
if (!target.getController().isOpponentOf(ai)) {
|
||||||
|
|||||||
@@ -1811,7 +1811,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
} else // This is an intrinsic effect that blinks the card (e.g. Obzedat, Ghost Council), no need to
|
} else // This is an intrinsic effect that blinks the card (e.g. Obzedat, Ghost Council), no need to
|
||||||
// return the commander to the Command zone.
|
// return the commander to the Command zone.
|
||||||
if (subApi == ApiType.DelayedTrigger) {
|
if (subApi == ApiType.DelayedTrigger) {
|
||||||
SpellAbility exec = causeSub.getAdditionalAbility("Execute");
|
SpellAbility exec = causeSub.getAdditionalAbility("Execute");
|
||||||
if (exec != null && exec.getApi() == ApiType.ChangeZone) {
|
if (exec != null && exec.getApi() == ApiType.ChangeZone) {
|
||||||
// A blink effect implemented using a delayed trigger
|
// A blink effect implemented using a delayed trigger
|
||||||
return !"Exile".equals(exec.getParam("Origin")) || !"Battlefield".equals(exec.getParam("Destination"));
|
return !"Exile".equals(exec.getParam("Origin")) || !"Battlefield".equals(exec.getParam("Destination"));
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package forge.ai.ability;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import forge.ai.*;
|
import forge.ai.*;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -22,11 +21,9 @@ public class DelayedTriggerAi extends SpellAbilityAi {
|
|||||||
// TODO: improve ai
|
// TODO: improve ai
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
SpellAbility trigsa = null;
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (trigsa == null) {
|
||||||
trigsa = sa.getAdditionalAbility("Execute");
|
return false;
|
||||||
} else {
|
|
||||||
trigsa = AbilityFactory.getAbility(sa.getHostCard(), sa.getParam("Execute"));
|
|
||||||
}
|
}
|
||||||
trigsa.setActivatingPlayer(ai);
|
trigsa.setActivatingPlayer(ai);
|
||||||
|
|
||||||
@@ -39,12 +36,11 @@ public class DelayedTriggerAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
SpellAbility trigsa = null;
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (trigsa == null) {
|
||||||
trigsa = sa.getAdditionalAbility("Execute");
|
return false;
|
||||||
} else {
|
|
||||||
trigsa = AbilityFactory.getAbility(sa.getHostCard(), sa.getParam("Execute"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||||
trigsa.setActivatingPlayer(ai);
|
trigsa.setActivatingPlayer(ai);
|
||||||
|
|
||||||
@@ -143,11 +139,9 @@ public class DelayedTriggerAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generic logic
|
// Generic logic
|
||||||
SpellAbility trigsa = null;
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (trigsa == null) {
|
||||||
trigsa = sa.getAdditionalAbility("Execute");
|
return false;
|
||||||
} else {
|
|
||||||
trigsa = AbilityFactory.getAbility(sa.getHostCard(), sa.getParam("Execute"));
|
|
||||||
}
|
}
|
||||||
trigsa.setActivatingPlayer(ai);
|
trigsa.setActivatingPlayer(ai);
|
||||||
return AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(trigsa);
|
return AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(trigsa);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.ai.ability;
|
|||||||
import forge.ai.*;
|
import forge.ai.*;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
@@ -193,7 +194,7 @@ public class FightAi extends SpellAbilityAi {
|
|||||||
for (Card humanCreature : humCreatures) {
|
for (Card humanCreature : humCreatures) {
|
||||||
for (Card aiCreature : aiCreatures) {
|
for (Card aiCreature : aiCreatures) {
|
||||||
if (source.isSpell()) { // heroic triggers adding counters and prowess
|
if (source.isSpell()) { // heroic triggers adding counters and prowess
|
||||||
final int bonus = getSpellBonus(aiCreature);
|
final int bonus = getSpellBonus(aiCreature);
|
||||||
power += bonus;
|
power += bonus;
|
||||||
toughness += bonus;
|
toughness += bonus;
|
||||||
}
|
}
|
||||||
@@ -247,28 +248,32 @@ public class FightAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the bonus from Heroic +1/+1 counters or Prowess
|
* Compute the bonus from Heroic +1/+1 counters or Prowess
|
||||||
*/
|
*/
|
||||||
private static int getSpellBonus(final Card aiCreature) {
|
private static int getSpellBonus(final Card aiCreature) {
|
||||||
for (Trigger t : aiCreature.getTriggers()) {
|
for (Trigger t : aiCreature.getTriggers()) {
|
||||||
if (t.getMode() == TriggerType.SpellCast) {
|
if (t.getMode() == TriggerType.SpellCast) {
|
||||||
final Map<String, String> params = t.getMapParams();
|
SpellAbility sa = t.ensureAbility();
|
||||||
if ("Card.Self".equals(params.get("TargetsValid")) && "You".equals(params.get("ValidActivatingPlayer"))
|
final Map<String, String> params = t.getMapParams();
|
||||||
&& params.containsKey("Execute")) {
|
if (sa == null) {
|
||||||
SpellAbility heroic = AbilityFactory.getAbility(aiCreature.getSVar(params.get("Execute")),aiCreature);
|
continue;
|
||||||
if ("Self".equals(heroic.getParam("Defined")) && "P1P1".equals(heroic.getParam("CounterType"))) {
|
}
|
||||||
return AbilityUtils.calculateAmount(aiCreature, heroic.getParam("CounterNum"), heroic);
|
if (ApiType.PutCounter.equals(sa.getApi())) {
|
||||||
}
|
if ("Card.Self".equals(params.get("TargetsValid")) && "You".equals(params.get("ValidActivatingPlayer"))) {
|
||||||
break;
|
SpellAbility heroic = AbilityFactory.getAbility(aiCreature.getSVar(params.get("Execute")),aiCreature);
|
||||||
}
|
if ("Self".equals(heroic.getParam("Defined")) && "P1P1".equals(heroic.getParam("CounterType"))) {
|
||||||
if ("ProwessPump".equals(params.get("Execute"))) {
|
return AbilityUtils.calculateAmount(aiCreature, heroic.getParam("CounterNum"), heroic);
|
||||||
return 1;
|
}
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else if (ApiType.Pump.equals(sa.getApi())) {
|
||||||
return 0;
|
// TODO add prowess boost
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean shouldFight(Card fighter, Card opponent, int pumpAttack, int pumpDefense) {
|
private static boolean shouldFight(Card fighter, Card opponent, int pumpAttack, int pumpDefense) {
|
||||||
if (canKill(fighter, opponent, pumpAttack)) {
|
if (canKill(fighter, opponent, pumpAttack)) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.*;
|
import forge.ai.*;
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -16,12 +15,11 @@ public class ImmediateTriggerAi extends SpellAbilityAi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellAbility trigsa = null;
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (trigsa == null) {
|
||||||
trigsa = sa.getAdditionalAbility("Execute");
|
return false;
|
||||||
} else {
|
|
||||||
trigsa = AbilityFactory.getAbility(sa.getHostCard(), sa.getParam("Execute"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigsa.setActivatingPlayer(ai);
|
trigsa.setActivatingPlayer(ai);
|
||||||
|
|
||||||
if (trigsa instanceof AbilitySub) {
|
if (trigsa instanceof AbilitySub) {
|
||||||
@@ -33,12 +31,11 @@ public class ImmediateTriggerAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
SpellAbility trigsa = null;
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (trigsa == null) {
|
||||||
trigsa = sa.getAdditionalAbility("Execute");
|
return false;
|
||||||
} else {
|
|
||||||
trigsa = AbilityFactory.getAbility(sa.getHostCard(), sa.getParam("Execute"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||||
trigsa.setActivatingPlayer(ai);
|
trigsa.setActivatingPlayer(ai);
|
||||||
|
|
||||||
@@ -56,12 +53,11 @@ public class ImmediateTriggerAi extends SpellAbilityAi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellAbility trigsa = null;
|
SpellAbility trigsa = sa.getAdditionalAbility("Execute");
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (trigsa == null) {
|
||||||
trigsa = sa.getAdditionalAbility("Execute");
|
return false;
|
||||||
} else {
|
|
||||||
trigsa = AbilityFactory.getAbility(sa.getHostCard(), sa.getParam("Execute"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigsa.setActivatingPlayer(ai);
|
trigsa.setActivatingPlayer(ai);
|
||||||
return AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(trigsa);
|
return AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(trigsa);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ public final class AbilityFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api == ApiType.DelayedTrigger && mapParams.containsKey("Execute")) {
|
if ((api == ApiType.DelayedTrigger || api == ApiType.ImmediateTrigger) && mapParams.containsKey("Execute")) {
|
||||||
spellAbility.setSVar(mapParams.get("Execute"), sVarHolder.getSVar(mapParams.get("Execute")));
|
spellAbility.setSVar(mapParams.get("Execute"), sVarHolder.getSVar(mapParams.get("Execute")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ public abstract class SpellAbilityEffect {
|
|||||||
+ " exile it instead of putting it anywhere else.";
|
+ " exile it instead of putting it anywhere else.";
|
||||||
String effect = "DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Battlefield | Destination$ " + zone;
|
String effect = "DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Battlefield | Destination$ " + zone;
|
||||||
|
|
||||||
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true);
|
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true, null);
|
||||||
re.setLayer(ReplacementLayer.Other);
|
re.setLayer(ReplacementLayer.Other);
|
||||||
|
|
||||||
re.setOverridingAbility(AbilityFactory.getAbility(effect, eff));
|
re.setOverridingAbility(AbilityFactory.getAbility(effect, eff));
|
||||||
|
|||||||
@@ -159,8 +159,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
// Grant triggers
|
// Grant triggers
|
||||||
final List<Trigger> addedTriggers = Lists.newArrayList();
|
final List<Trigger> addedTriggers = Lists.newArrayList();
|
||||||
for (final String s : triggers) {
|
for (final String s : triggers) {
|
||||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(AbilityUtils.getSVar(sa, s), c, false);
|
final Trigger parsedTrigger = TriggerHandler.parseTrigger(AbilityUtils.getSVar(sa, s), c, false, sa);
|
||||||
parsedTrigger.setOverridingAbility(AbilityFactory.getAbility(c, parsedTrigger.getParam("Execute"), sa));
|
|
||||||
parsedTrigger.setOriginalHost(source);
|
parsedTrigger.setOriginalHost(source);
|
||||||
addedTriggers.add(parsedTrigger);
|
addedTriggers.add(parsedTrigger);
|
||||||
}
|
}
|
||||||
@@ -168,7 +167,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
// give replacement effects
|
// give replacement effects
|
||||||
final List<ReplacementEffect> addedReplacements = Lists.newArrayList();
|
final List<ReplacementEffect> addedReplacements = Lists.newArrayList();
|
||||||
for (final String s : replacements) {
|
for (final String s : replacements) {
|
||||||
addedReplacements.add(ReplacementHandler.parseReplacement(AbilityUtils.getSVar(sa, s), c, false));
|
addedReplacements.add(ReplacementHandler.parseReplacement(AbilityUtils.getSVar(sa, s), c, false, sa));
|
||||||
}
|
}
|
||||||
|
|
||||||
// give static abilities (should only be used by cards to give
|
// give static abilities (should only be used by cards to give
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class DelayedTriggerEffect extends SpellAbilityEffect {
|
|||||||
Card lki = CardUtil.getLKICopy(gameCard);
|
Card lki = CardUtil.getLKICopy(gameCard);
|
||||||
lki.clearControllers();
|
lki.clearControllers();
|
||||||
lki.setOwner(sa.getActivatingPlayer());
|
lki.setOwner(sa.getActivatingPlayer());
|
||||||
final Trigger delTrig = TriggerHandler.parseTrigger(mapParams, lki, sa.isIntrinsic());
|
final Trigger delTrig = TriggerHandler.parseTrigger(mapParams, lki, sa.isIntrinsic(), null);
|
||||||
delTrig.setSpawningAbility(sa.copy(lki, sa.getActivatingPlayer(), true));
|
delTrig.setSpawningAbility(sa.copy(lki, sa.getActivatingPlayer(), true));
|
||||||
|
|
||||||
if (triggerRemembered != null) {
|
if (triggerRemembered != null) {
|
||||||
@@ -81,7 +81,7 @@ public class DelayedTriggerEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapParams.containsKey("Execute") || sa.hasAdditionalAbility("Execute")) {
|
if (sa.hasAdditionalAbility("Execute")) {
|
||||||
AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
||||||
// need to reset the parent, additionalAbility does set it to this
|
// need to reset the parent, additionalAbility does set it to this
|
||||||
overridingSA.setParent(null);
|
overridingSA.setParent(null);
|
||||||
@@ -96,7 +96,7 @@ public class DelayedTriggerEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
delTrig.setOverridingAbility(overridingSA);
|
delTrig.setOverridingAbility(overridingSA);
|
||||||
}
|
}
|
||||||
final TriggerHandler trigHandler = sa.getActivatingPlayer().getGame().getTriggerHandler();
|
final TriggerHandler trigHandler = game.getTriggerHandler();
|
||||||
if (mapParams.containsKey("DelayedTriggerDefinedPlayer")) { // on sb's next turn
|
if (mapParams.containsKey("DelayedTriggerDefinedPlayer")) { // on sb's next turn
|
||||||
Player p = Iterables.getFirst(AbilityUtils.getDefinedPlayers(sa.getHostCard(), mapParams.get("DelayedTriggerDefinedPlayer"), sa), null);
|
Player p = Iterables.getFirst(AbilityUtils.getDefinedPlayers(sa.getHostCard(), mapParams.get("DelayedTriggerDefinedPlayer"), sa), null);
|
||||||
trigHandler.registerPlayerDefinedDelayedTrigger(p, delTrig);
|
trigHandler.registerPlayerDefinedDelayedTrigger(p, delTrig);
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public class EffectEffect extends SpellAbilityEffect {
|
|||||||
for (final String s : effectReplacementEffects) {
|
for (final String s : effectReplacementEffects) {
|
||||||
final String actualReplacement = AbilityUtils.getSVar(sa, s);
|
final String actualReplacement = AbilityUtils.getSVar(sa, s);
|
||||||
|
|
||||||
final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, eff, true);
|
final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, eff, true, sa);
|
||||||
parsedReplacement.setActiveZone(EnumSet.of(ZoneType.Command));
|
parsedReplacement.setActiveZone(EnumSet.of(ZoneType.Command));
|
||||||
parsedReplacement.setIntrinsic(true);
|
parsedReplacement.setIntrinsic(true);
|
||||||
eff.addReplacementEffect(parsedReplacement);
|
eff.addReplacementEffect(parsedReplacement);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect {
|
|||||||
Card lki = CardUtil.getLKICopy(gameCard);
|
Card lki = CardUtil.getLKICopy(gameCard);
|
||||||
lki.clearControllers();
|
lki.clearControllers();
|
||||||
lki.setOwner(sa.getActivatingPlayer());
|
lki.setOwner(sa.getActivatingPlayer());
|
||||||
final Trigger immediateTrig = TriggerHandler.parseTrigger(mapParams, lki, sa.isIntrinsic());
|
final Trigger immediateTrig = TriggerHandler.parseTrigger(mapParams, lki, sa.isIntrinsic(), null);
|
||||||
immediateTrig.setSpawningAbility(sa.copy(lki, sa.getActivatingPlayer(), true));
|
immediateTrig.setSpawningAbility(sa.copy(lki, sa.getActivatingPlayer(), true));
|
||||||
|
|
||||||
// Need to copy paid costs
|
// Need to copy paid costs
|
||||||
@@ -74,7 +74,7 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapParams.containsKey("Execute") || sa.hasAdditionalAbility("Execute")) {
|
if (sa.hasAdditionalAbility("Execute")) {
|
||||||
AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
||||||
// need to set Parent to null, otherwise it might have wrong root ability
|
// need to set Parent to null, otherwise it might have wrong root ability
|
||||||
overridingSA.setParent(null);
|
overridingSA.setParent(null);
|
||||||
@@ -85,9 +85,8 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
immediateTrig.setOverridingAbility(overridingSA);
|
immediateTrig.setOverridingAbility(overridingSA);
|
||||||
}
|
}
|
||||||
final TriggerHandler trigHandler = sa.getActivatingPlayer().getGame().getTriggerHandler();
|
|
||||||
|
|
||||||
// Instead of registering this, add to the delayed triggers as an immediate trigger type? Which means it'll fire as soon as possible
|
// Instead of registering this, add to the delayed triggers as an immediate trigger type? Which means it'll fire as soon as possible
|
||||||
trigHandler.registerDelayedTrigger(immediateTrig);
|
game.getTriggerHandler().registerDelayedTrigger(immediateTrig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5932,21 +5932,20 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
|
|
||||||
public boolean hasETBTrigger(final boolean drawbackOnly) {
|
public boolean hasETBTrigger(final boolean drawbackOnly) {
|
||||||
for (final Trigger tr : getTriggers()) {
|
for (final Trigger tr : getTriggers()) {
|
||||||
final Map<String, String> params = tr.getMapParams();
|
|
||||||
if (tr.getMode() != TriggerType.ChangesZone) {
|
if (tr.getMode() != TriggerType.ChangesZone) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.get("Destination").equals(ZoneType.Battlefield.toString())) {
|
if (!tr.getParam("Destination").equals(ZoneType.Battlefield.toString())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("ValidCard") && !params.get("ValidCard").contains("Self")) {
|
if (tr.hasParam("ValidCard") && !tr.getParam("ValidCard").contains("Self")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (drawbackOnly && params.containsKey("Execute")){
|
if (drawbackOnly) {
|
||||||
String exec = this.getSVar(params.get("Execute"));
|
SpellAbility sa = tr.ensureAbility();
|
||||||
if (exec.contains("AB$")) {
|
if (sa == null || sa.isActivatedAbility()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -664,6 +664,7 @@ public class CardFactory {
|
|||||||
if (origSVars.containsKey(s)) {
|
if (origSVars.containsKey(s)) {
|
||||||
final String actualTrigger = origSVars.get(s);
|
final String actualTrigger = origSVars.get(s);
|
||||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, out, true);
|
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, out, true);
|
||||||
|
parsedTrigger.setOriginalHost(host);
|
||||||
state.addTrigger(parsedTrigger);
|
state.addTrigger(parsedTrigger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -687,6 +688,7 @@ public class CardFactory {
|
|||||||
if (origSVars.containsKey(s)) {
|
if (origSVars.containsKey(s)) {
|
||||||
final String actualAbility = origSVars.get(s);
|
final String actualAbility = origSVars.get(s);
|
||||||
final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, out);
|
final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, out);
|
||||||
|
grantedAbility.setOriginalHost(host);
|
||||||
grantedAbility.setIntrinsic(true);
|
grantedAbility.setIntrinsic(true);
|
||||||
state.addSpellAbility(grantedAbility);
|
state.addSpellAbility(grantedAbility);
|
||||||
}
|
}
|
||||||
@@ -700,6 +702,7 @@ public class CardFactory {
|
|||||||
if (origSVars.containsKey(s)) {
|
if (origSVars.containsKey(s)) {
|
||||||
final String actualStatic = origSVars.get(s);
|
final String actualStatic = origSVars.get(s);
|
||||||
final StaticAbility grantedStatic = new StaticAbility(actualStatic, out);
|
final StaticAbility grantedStatic = new StaticAbility(actualStatic, out);
|
||||||
|
grantedStatic.setOriginalHost(host);
|
||||||
grantedStatic.setIntrinsic(true);
|
grantedStatic.setIntrinsic(true);
|
||||||
state.addStaticAbility(grantedStatic);
|
state.addStaticAbility(grantedStatic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2227,7 +2227,7 @@ public class CardFactoryUtil {
|
|||||||
final String abStringAfflict = "DB$ LoseLife | Defined$ TriggeredDefendingPlayer" +
|
final String abStringAfflict = "DB$ LoseLife | Defined$ TriggeredDefendingPlayer" +
|
||||||
" | LifeAmount$ " + n;
|
" | LifeAmount$ " + n;
|
||||||
|
|
||||||
final Trigger afflictTrigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
final Trigger afflictTrigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic, null);
|
||||||
afflictTrigger.setOverridingAbility(AbilityFactory.getAbility(abStringAfflict, card));
|
afflictTrigger.setOverridingAbility(AbilityFactory.getAbility(abStringAfflict, card));
|
||||||
|
|
||||||
inst.addTrigger(afflictTrigger);
|
inst.addTrigger(afflictTrigger);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.game.replacement;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
|
import forge.game.IHasSVars;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
@@ -370,7 +371,10 @@ public class ReplacementHandler {
|
|||||||
* @return A finished instance
|
* @return A finished instance
|
||||||
*/
|
*/
|
||||||
public static ReplacementEffect parseReplacement(final String repParse, final Card host, final boolean intrinsic) {
|
public static ReplacementEffect parseReplacement(final String repParse, final Card host, final boolean intrinsic) {
|
||||||
return ReplacementHandler.parseReplacement(parseParams(repParse), host, intrinsic);
|
return parseReplacement(repParse, host, intrinsic, host);
|
||||||
|
}
|
||||||
|
public static ReplacementEffect parseReplacement(final String repParse, final Card host, final boolean intrinsic, final IHasSVars sVarHolder) {
|
||||||
|
return ReplacementHandler.parseReplacement(parseParams(repParse), host, intrinsic, sVarHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> parseParams(final String repParse) {
|
public static Map<String, String> parseParams(final String repParse) {
|
||||||
@@ -388,7 +392,7 @@ public class ReplacementHandler {
|
|||||||
* The card that hosts the replacement effect
|
* The card that hosts the replacement effect
|
||||||
* @return The finished instance
|
* @return The finished instance
|
||||||
*/
|
*/
|
||||||
private static ReplacementEffect parseReplacement(final Map<String, String> mapParams, final Card host, final boolean intrinsic) {
|
private static ReplacementEffect parseReplacement(final Map<String, String> mapParams, final Card host, final boolean intrinsic, final IHasSVars sVarHolder) {
|
||||||
final ReplacementType rt = ReplacementType.smartValueOf(mapParams.get("Event"));
|
final ReplacementType rt = ReplacementType.smartValueOf(mapParams.get("Event"));
|
||||||
ReplacementEffect ret = rt.createReplacement(mapParams, host, intrinsic);
|
ReplacementEffect ret = rt.createReplacement(mapParams, host, intrinsic);
|
||||||
|
|
||||||
@@ -397,8 +401,8 @@ public class ReplacementHandler {
|
|||||||
ret.setActiveZone(EnumSet.copyOf(ZoneType.listValueOf(activeZones)));
|
ret.setActiveZone(EnumSet.copyOf(ZoneType.listValueOf(activeZones)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapParams.containsKey("ReplaceWith")) {
|
if (mapParams.containsKey("ReplaceWith") && sVarHolder != null) {
|
||||||
ret.setOverridingAbility(AbilityFactory.getAbility(host, mapParams.get("ReplaceWith"), ret));
|
ret.setOverridingAbility(AbilityFactory.getAbility(host, mapParams.get("ReplaceWith"), sVarHolder));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -781,8 +781,7 @@ public final class StaticAbilityContinuous {
|
|||||||
// add Replacement effects
|
// add Replacement effects
|
||||||
if (addReplacements != null) {
|
if (addReplacements != null) {
|
||||||
for (String rep : addReplacements) {
|
for (String rep : addReplacements) {
|
||||||
final ReplacementEffect actualRep = ReplacementHandler.parseReplacement(rep, affectedCard, false);
|
final ReplacementEffect actualRep = ReplacementHandler.parseReplacement(rep, affectedCard, false, stAb);
|
||||||
actualRep.setIntrinsic(false);
|
|
||||||
addedReplacementEffects.add(actualRep);
|
addedReplacementEffects.add(actualRep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -790,17 +789,12 @@ public final class StaticAbilityContinuous {
|
|||||||
// add triggers
|
// add triggers
|
||||||
if (addTriggers != null) {
|
if (addTriggers != null) {
|
||||||
for (final String trigger : addTriggers) {
|
for (final String trigger : addTriggers) {
|
||||||
final Trigger actualTrigger = TriggerHandler.parseTrigger(trigger, affectedCard, false);
|
final Trigger actualTrigger = TriggerHandler.parseTrigger(trigger, affectedCard, false, stAb);
|
||||||
// if the trigger has Execute param, which most trigger gained by Static Abilties should have
|
// if the trigger has Execute param, which most trigger gained by Static Abilties should have
|
||||||
// turn them into SpellAbility object before adding to card
|
// turn them into SpellAbility object before adding to card
|
||||||
// with that the TargetedCard does not need the Svars added to them anymore
|
// with that the TargetedCard does not need the Svars added to them anymore
|
||||||
// but only do it if the trigger doesn't already have a overriding ability
|
// but only do it if the trigger doesn't already have a overriding ability
|
||||||
if (actualTrigger.hasParam("Execute") && actualTrigger.getOverridingAbility() == null) {
|
|
||||||
// set overriding ability to the trigger
|
|
||||||
actualTrigger.setOverridingAbility(AbilityFactory.getAbility(affectedCard, actualTrigger.getParam("Execute"), stAb));
|
|
||||||
}
|
|
||||||
actualTrigger.setOriginalHost(hostCard);
|
actualTrigger.setOriginalHost(hostCard);
|
||||||
actualTrigger.setIntrinsic(false);
|
|
||||||
addedTrigger.add(actualTrigger);
|
addedTrigger.add(actualTrigger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.game.trigger;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.IHasSVars;
|
||||||
import forge.game.TriggerReplacementBase;
|
import forge.game.TriggerReplacementBase;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
@@ -562,12 +563,16 @@ public abstract class Trigger extends TriggerReplacementBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpellAbility ensureAbility() {
|
public SpellAbility ensureAbility(final IHasSVars sVarHolder) {
|
||||||
SpellAbility sa = getOverridingAbility();
|
SpellAbility sa = getOverridingAbility();
|
||||||
if (sa == null && hasParam("Execute")) {
|
if (sa == null && hasParam("Execute")) {
|
||||||
sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute"));
|
sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute"), sVarHolder);
|
||||||
setOverridingAbility(sa);
|
setOverridingAbility(sa);
|
||||||
}
|
}
|
||||||
return sa;
|
return sa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpellAbility ensureAbility() {
|
||||||
|
return ensureAbility(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.game.trigger;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GlobalRuleChange;
|
import forge.game.GlobalRuleChange;
|
||||||
|
import forge.game.IHasSVars;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
@@ -123,9 +124,13 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Trigger parseTrigger(final String trigParse, final Card host, final boolean intrinsic) {
|
public static Trigger parseTrigger(final String trigParse, final Card host, final boolean intrinsic) {
|
||||||
|
return parseTrigger(trigParse, host, intrinsic, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Trigger parseTrigger(final String trigParse, final Card host, final boolean intrinsic, final IHasSVars sVarHolder) {
|
||||||
try {
|
try {
|
||||||
final Map<String, String> mapParams = TriggerHandler.parseParams(trigParse);
|
final Map<String, String> mapParams = TriggerHandler.parseParams(trigParse);
|
||||||
return TriggerHandler.parseTrigger(mapParams, host, intrinsic);
|
return TriggerHandler.parseTrigger(mapParams, host, intrinsic, sVarHolder);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "TriggerHandler:parseTrigger failed to parse";
|
String msg = "TriggerHandler:parseTrigger failed to parse";
|
||||||
Sentry.getContext().recordBreadcrumb(
|
Sentry.getContext().recordBreadcrumb(
|
||||||
@@ -137,12 +142,15 @@ public class TriggerHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Trigger parseTrigger(final Map<String, String> mapParams, final Card host, final boolean intrinsic) {
|
public static Trigger parseTrigger(final Map<String, String> mapParams, final Card host, final boolean intrinsic, final IHasSVars sVarHolder) {
|
||||||
Trigger ret = null;
|
Trigger ret = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final TriggerType type = TriggerType.smartValueOf(mapParams.get("Mode"));
|
final TriggerType type = TriggerType.smartValueOf(mapParams.get("Mode"));
|
||||||
ret = type.createTrigger(mapParams, host, intrinsic);
|
ret = type.createTrigger(mapParams, host, intrinsic);
|
||||||
|
if (sVarHolder != null) {
|
||||||
|
ret.ensureAbility(sVarHolder);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "TriggerHandler:parseTrigger failed to parse";
|
String msg = "TriggerHandler:parseTrigger failed to parse";
|
||||||
Sentry.getContext().recordBreadcrumb(
|
Sentry.getContext().recordBreadcrumb(
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public final class CardRelationMatrixGenerator {
|
|||||||
|
|
||||||
public static HashMap<String,HashMap<String,List<Map.Entry<PaperCard,Integer>>>> cardPools = new HashMap<>();
|
public static HashMap<String,HashMap<String,List<Map.Entry<PaperCard,Integer>>>> cardPools = new HashMap<>();
|
||||||
|
|
||||||
public static Map<String, Map<String,List<List<String>>>> ldaPools = new HashMap();
|
public static Map<String, Map<String,List<List<String>>>> ldaPools = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
To ensure that only cards with at least 14 connections (as 14*4+4=60) are included in the card based deck
|
To ensure that only cards with at least 14 connections (as 14*4+4=60) are included in the card based deck
|
||||||
generation pools
|
generation pools
|
||||||
|
|||||||
Reference in New Issue
Block a user