From ad4123c6515bdc7eb5c5f1baf8dbc29bc924e394 Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 23 Jul 2020 17:44:55 +0300 Subject: [PATCH 1/3] - "Whenever one or more .... fights" (e.g. Neyith) --- .../java/forge/game/ability/AbilityKey.java | 2 + .../game/ability/effects/FightEffect.java | 5 ++ .../forge/game/trigger/TriggerFightOnce.java | 75 +++++++++++++++++++ .../java/forge/game/trigger/TriggerType.java | 1 + 4 files changed, 83 insertions(+) create mode 100644 forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index 4821b088c8a..dcf0ce25847 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -62,6 +62,8 @@ public enum AbilityKey { Explorer("Explorer"), Event("Event"), Fighter("Fighter"), + Fighter1("Fighter1"), + Fighter2("Fighter2"), FirstTime("FirstTime"), Fizzle("Fizzle"), IsCombat("IsCombat"), // TODO confirm that this and IsCombatDamage can be merged diff --git a/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java index 7ae2fc18dc7..8cbd9b92e1a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java @@ -63,6 +63,11 @@ public class FightEffect extends DamageBaseEffect { runParams.put(AbilityKey.Fighter, c); game.getTriggerHandler().runTrigger(TriggerType.Fight, runParams, false); } + + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Fighter1, fighters.get(0)); + runParams.put(AbilityKey.Fighter2, fighters.get(1)); + game.getTriggerHandler().runTrigger(TriggerType.FightOnce, runParams, false); } private static List getFighters(SpellAbility sa) { diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java b/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java new file mode 100644 index 00000000000..a06472bd049 --- /dev/null +++ b/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java @@ -0,0 +1,75 @@ +/* + * 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 . + */ +package forge.game.trigger; + +import forge.game.ability.AbilityKey; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; +import forge.util.Localizer; + +import java.util.Map; + +public class TriggerFightOnce extends Trigger { + + /** + *

+ * Constructor for Trigger_Fight. + *

+ * + * @param params + * a {@link java.util.HashMap} object. + * @param host + * a {@link forge.game.card.Card} object. + * @param intrinsic + * the intrinsic + */ + public TriggerFightOnce(final Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /** {@inheritDoc} + * @param runParams*/ + @Override + public final boolean performTest(final Map runParams) { + final Card fighter1 = (Card) runParams.get(AbilityKey.Fighter1); + final Card fighter2 = (Card) runParams.get(AbilityKey.Fighter2); + + if (hasParam("ValidCard")) { + return fighter1.isValid(getParam("ValidCard").split(","), + getHostCard().getController(), getHostCard(), null) + || fighter2.isValid(getParam("ValidCard").split(","), + getHostCard().getController(), getHostCard(), null); + } + return true; + } + + /** {@inheritDoc} */ + @Override + public final void setTriggeringObjects(final SpellAbility sa, Map runParams) { + sa.setTriggeringObjectsFrom(runParams, AbilityKey.Fighter1, AbilityKey.Fighter2); + } + + @Override + public String getImportantStackObjects(SpellAbility sa) { + StringBuilder sb = new StringBuilder(); + sb.append(Localizer.getInstance().getMessage("lblFighter")).append(" 1: ").append(sa.getTriggeringObject(AbilityKey.Fighter1)).append(", "); + sb.append(Localizer.getInstance().getMessage("lblFighter")).append(" 2: ").append(sa.getTriggeringObject(AbilityKey.Fighter2)); + return sb.toString(); + } +} + diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java index e3f0b5f36fd..41cfe2dc908 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java @@ -60,6 +60,7 @@ public enum TriggerType { Exploited(TriggerExploited.class), Explores(TriggerExplores.class), Fight(TriggerFight.class), + FightOnce(TriggerFightOnce.class), FlippedCoin(TriggerFlippedCoin.class), Immediate(TriggerImmediate.class), Investigated(TriggerInvestigated.class), From 7db9a7b86cbd5a62108ec2a38b649e9304ce1b75 Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 23 Jul 2020 18:34:19 +0300 Subject: [PATCH 2/3] - Rewrite FightOnce trigger to use a list. - Add support to test for a valid blocked attacker in TriggerBlockersDeclared. - Add Neyith of the Dire Hunt. --- .../java/forge/game/ability/AbilityKey.java | 3 +-- .../game/ability/effects/FightEffect.java | 3 +-- .../game/trigger/TriggerBlockersDeclared.java | 14 +++++++++++ .../forge/game/trigger/TriggerFightOnce.java | 23 +++++++++++-------- .../cardsfolder/n/neyith_of_the_dire_hunt.txt | 11 +++++++++ 5 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 forge-gui/res/cardsfolder/n/neyith_of_the_dire_hunt.txt diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index dcf0ce25847..90a818bbc3f 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -62,8 +62,7 @@ public enum AbilityKey { Explorer("Explorer"), Event("Event"), Fighter("Fighter"), - Fighter1("Fighter1"), - Fighter2("Fighter2"), + Fighters("Fighters"), FirstTime("FirstTime"), Fizzle("Fizzle"), IsCombat("IsCombat"), // TODO confirm that this and IsCombatDamage can be merged diff --git a/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java index 8cbd9b92e1a..bbb39fb8e2c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FightEffect.java @@ -65,8 +65,7 @@ public class FightEffect extends DamageBaseEffect { } final Map runParams = AbilityKey.newMap(); - runParams.put(AbilityKey.Fighter1, fighters.get(0)); - runParams.put(AbilityKey.Fighter2, fighters.get(1)); + runParams.put(AbilityKey.Fighters, fighters); game.getTriggerHandler().runTrigger(TriggerType.FightOnce, runParams, false); } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java b/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java index 5263ebd9de9..925cf0d5193 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java @@ -22,6 +22,7 @@ import forge.game.card.Card; import forge.game.spellability.SpellAbility; import forge.util.Localizer; +import java.util.List; import java.util.Map; /** @@ -48,6 +49,19 @@ public class TriggerBlockersDeclared extends Trigger { * @param runParams*/ @Override public final boolean performTest(final Map runParams) { + if (hasParam("ValidBlockedAttacker")) { + List attackers = (List)runParams.get(AbilityKey.Attackers); + for (Card attacker : attackers) { + if (attacker.getGame().getCombat() == null) { break; } + if (attacker.isValid(getParam("ValidBlockedAttacker").split(","), + getHostCard().getController(), getHostCard(), null) + && !attacker.getGame().getCombat().getBlockers(attacker).isEmpty()) { + return true; + } + } + return false; + } + return true; } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java b/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java index a06472bd049..3fa0b32daf8 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerFightOnce.java @@ -22,6 +22,7 @@ import forge.game.card.Card; import forge.game.spellability.SpellAbility; import forge.util.Localizer; +import java.util.List; import java.util.Map; public class TriggerFightOnce extends Trigger { @@ -46,29 +47,33 @@ public class TriggerFightOnce extends Trigger { * @param runParams*/ @Override public final boolean performTest(final Map runParams) { - final Card fighter1 = (Card) runParams.get(AbilityKey.Fighter1); - final Card fighter2 = (Card) runParams.get(AbilityKey.Fighter2); + final List fighters = (List) runParams.get(AbilityKey.Fighters); if (hasParam("ValidCard")) { - return fighter1.isValid(getParam("ValidCard").split(","), - getHostCard().getController(), getHostCard(), null) - || fighter2.isValid(getParam("ValidCard").split(","), - getHostCard().getController(), getHostCard(), null); + for (Card fighter : fighters) { + if (fighter.isValid(getParam("ValidCard").split(","), + getHostCard().getController(), getHostCard(), null)) { + return true; + } + } + return false; } + return true; } /** {@inheritDoc} */ @Override public final void setTriggeringObjects(final SpellAbility sa, Map runParams) { - sa.setTriggeringObjectsFrom(runParams, AbilityKey.Fighter1, AbilityKey.Fighter2); + sa.setTriggeringObjectsFrom(runParams, AbilityKey.Fighters); } @Override public String getImportantStackObjects(SpellAbility sa) { StringBuilder sb = new StringBuilder(); - sb.append(Localizer.getInstance().getMessage("lblFighter")).append(" 1: ").append(sa.getTriggeringObject(AbilityKey.Fighter1)).append(", "); - sb.append(Localizer.getInstance().getMessage("lblFighter")).append(" 2: ").append(sa.getTriggeringObject(AbilityKey.Fighter2)); + List fighters = (List)sa.getTriggeringObject(AbilityKey.Fighters); + sb.append(Localizer.getInstance().getMessage("lblFighter")).append(" 1: ").append(fighters.get(0)).append(", "); + sb.append(Localizer.getInstance().getMessage("lblFighter")).append(" 2: ").append(fighters.get(1)); return sb.toString(); } } diff --git a/forge-gui/res/cardsfolder/n/neyith_of_the_dire_hunt.txt b/forge-gui/res/cardsfolder/n/neyith_of_the_dire_hunt.txt new file mode 100644 index 00000000000..6928d885d20 --- /dev/null +++ b/forge-gui/res/cardsfolder/n/neyith_of_the_dire_hunt.txt @@ -0,0 +1,11 @@ +Name:Neyith of the Dire Hunt +ManaCost:2 G G +Types:Legendary Creature Human Warrior +PT:3/3 +T:Mode$ FightOnce | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever one or more creatures you control fight or become blocked, draw a card. +T:Mode$ BlockersDeclared | ValidBlockedAttacker$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDraw | Secondary$ True | TriggerDescription$ Whenever one or more creatures you control fight or become blocked, draw a card. +SVar:TrigDraw:DB$ Draw | NumCards$ 1 +T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, you may pay {2}{R/G}. If you do, double target creature's power until end of turn. That creature must be blocked this combat if able. +SVar:TrigPump:AB$ Pump | Cost$ 2 RG | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +X | References$ X | KW$ HIDDEN CARDNAME must be blocked if able. +SVar:X:Targeted$CardPower +Oracle:Whenever one or more creatures you control fight or become blocked, draw a card.\nAt the beginning of combat on your turn, you may pay {2}{R/G}. If you do, double target creature's power until end of turn. That creature must be blocked this combat if able. ({R/G} can be paid with either {R} or {G}.) From 335ea618222fb7574b806377bff32061ecf5bb65 Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 23 Jul 2020 18:37:43 +0300 Subject: [PATCH 3/3] - Combat can't be null for the BlockersDeclared trigger (hopefully, anyway). --- .../main/java/forge/game/trigger/TriggerBlockersDeclared.java | 1 - 1 file changed, 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java b/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java index 925cf0d5193..f87230448be 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerBlockersDeclared.java @@ -52,7 +52,6 @@ public class TriggerBlockersDeclared extends Trigger { if (hasParam("ValidBlockedAttacker")) { List attackers = (List)runParams.get(AbilityKey.Attackers); for (Card attacker : attackers) { - if (attacker.getGame().getCombat() == null) { break; } if (attacker.isValid(getParam("ValidBlockedAttacker").split(","), getHostCard().getController(), getHostCard(), null) && !attacker.getGame().getCombat().getBlockers(attacker).isEmpty()) {