mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Regenerate rework (#3385)
* CardFactoryUtil: remove false keyword * CardFactoryUtil: remove wrong regenerate Keyword * CantRegenerate as Static * ~small fixes * RegenerationAbility as SubAbility to the Regeneration Effect * Card: use shieldCount instead of Collection * remove deprecated trigger * fix AiLogic vs AILogic * EffectAi: start of logic for CantRegenerate * EffectAi: try to do StackPeek for CantRegenerate * ~ use wither damage * AI prediction against Damage * CantRegenerate: begin logic against Combat Damage * AnimateAi: start logic for Bone Shaman * fix Runesword
This commit is contained in:
@@ -63,6 +63,7 @@ public final class AbilityFactory {
|
||||
"ChooseSubAbility", // Can choose a player via ChoosePlayer
|
||||
"CantChooseSubAbility", // Can't choose a player via ChoosePlayer
|
||||
"AnimateSubAbility", // For ChangeZone Effects to Animate before ETB
|
||||
"RegenerationAbility", // for Regeneration Effect
|
||||
"ReturnAbility" // for Delayed Trigger on Magpie
|
||||
);
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ public class FogEffect extends SpellAbilityEffect {
|
||||
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
|
||||
|
||||
game.getEndOfTurn().addUntil(new GameCommand() {
|
||||
private static final long serialVersionUID = -3297629217432253089L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
game.getAction().exile(eff, null);
|
||||
|
||||
@@ -2,7 +2,6 @@ package forge.game.ability.effects;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -28,11 +27,8 @@ public class RegenerateAllEffect extends RegenerateBaseEffect {
|
||||
final Game game = hostCard.getGame();
|
||||
final String valid = sa.getParamOrDefault("ValidCards", "");
|
||||
|
||||
CardCollectionView list = game.getCardsIn(ZoneType.Battlefield);
|
||||
list = CardLists.getValidCards(list, valid, hostCard.getController(), hostCard, sa);
|
||||
|
||||
// create Effect for Regeneration
|
||||
createRegenerationEffect(sa, list);
|
||||
createRegenerationEffect(sa, CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), valid, hostCard.getController(), hostCard, sa));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import forge.GameCommand;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
@@ -11,14 +13,15 @@ import forge.game.replacement.ReplacementEffect;
|
||||
import forge.game.replacement.ReplacementHandler;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.TriggerHandler;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
|
||||
|
||||
public void createRegenerationEffect(SpellAbility sa, final Iterable<Card> list) {
|
||||
public void createRegenerationEffect(SpellAbility sa, final Collection<Card> list) {
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final Card hostCard = sa.getHostCard();
|
||||
final Game game = hostCard.getGame();
|
||||
|
||||
@@ -41,6 +44,11 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
|
||||
SpellAbility saReg = AbilityFactory.getAbility(effect, eff);
|
||||
AbilitySub saExile = (AbilitySub)AbilityFactory.getAbility(exileEff, eff);
|
||||
|
||||
if (sa.hasAdditionalAbility("RegenerationAbility")) {
|
||||
AbilitySub trigSA = (AbilitySub)sa.getAdditionalAbility("RegenerationAbility").copy(eff, sa.getActivatingPlayer(), false);
|
||||
saExile.setSubAbility(trigSA);
|
||||
}
|
||||
|
||||
saReg.setSubAbility(saExile);
|
||||
re.setOverridingAbility(saReg);
|
||||
eff.addReplacementEffect(re);
|
||||
@@ -50,18 +58,6 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
|
||||
eff.addRemembered(AbilityUtils.getDefinedObjects(hostCard, sa.getParam("RememberObjects"), sa));
|
||||
}
|
||||
|
||||
if (sa.hasParam("RegenerationTrigger")) {
|
||||
final String str = sa.getSVar(sa.getParam("RegenerationTrigger"));
|
||||
|
||||
SpellAbility trigSA = AbilityFactory.getAbility(str, eff);
|
||||
|
||||
final String trigStr = "Mode$ Regenerated | ValidCause$ Effect.Self | TriggerZones$ Command "
|
||||
+ " | TriggerDescription$ " + trigSA.getDescription();
|
||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, eff, true);
|
||||
trigger.setOverridingAbility(trigSA);
|
||||
eff.addTrigger(trigger);
|
||||
}
|
||||
|
||||
// Copy text changes
|
||||
if (sa.isIntrinsic()) {
|
||||
eff.copyChangedTextFrom(hostCard);
|
||||
@@ -69,7 +65,7 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
|
||||
|
||||
// add RegenEffect as Shield to the Affected Cards
|
||||
for (final Card c : list) {
|
||||
c.addShield(eff);
|
||||
c.incShieldCount();
|
||||
}
|
||||
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
|
||||
game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap());
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Lang;
|
||||
|
||||
public class RegenerateEffect extends RegenerateBaseEffect {
|
||||
|
||||
@@ -15,26 +17,13 @@ public class RegenerateEffect extends RegenerateBaseEffect {
|
||||
@Override
|
||||
protected String getStackDescription(SpellAbility sa) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final List<Card> tgtCards = getTargetCards(sa);
|
||||
final List<Card> tgtCards = getDefinedCardsOrTargeted(sa);
|
||||
|
||||
if (tgtCards.size() > 0) {
|
||||
if (!tgtCards.isEmpty()) {
|
||||
sb.append("Regenerate ");
|
||||
|
||||
final Iterator<Card> it = tgtCards.iterator();
|
||||
while (it.hasNext()) {
|
||||
final Card tgtC = it.next();
|
||||
if (tgtC.isFaceDown()) {
|
||||
sb.append("Morph");
|
||||
} else {
|
||||
sb.append(tgtC);
|
||||
}
|
||||
|
||||
if (it.hasNext()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(Lang.joinHomogenous(tgtCards));
|
||||
sb.append(".");
|
||||
}
|
||||
sb.append(".");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -45,8 +34,26 @@ public class RegenerateEffect extends RegenerateBaseEffect {
|
||||
*/
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Game game = sa.getHostCard().getGame();
|
||||
CardCollection result = new CardCollection();
|
||||
|
||||
for (Card c : getDefinedCardsOrTargeted(sa)) {
|
||||
if (!c.isInPlay()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the object is still in game or if it was moved
|
||||
Card gameCard = game.getCardState(c, null);
|
||||
// gameCard is LKI in that case, the card is not in game anymore
|
||||
// or the timestamp did change
|
||||
// this should check Self too
|
||||
if (gameCard == null || !c.equalsWithTimestamp(gameCard)) {
|
||||
continue;
|
||||
}
|
||||
result.add(gameCard);
|
||||
}
|
||||
// create Effect for Regeneration
|
||||
createRegenerationEffect(sa, getDefinedCardsOrTargeted(sa));
|
||||
createRegenerationEffect(sa, result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.event.GameEventCardRegenerated;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
|
||||
public class RegenerationEffect extends SpellAbilityEffect {
|
||||
|
||||
@@ -21,9 +17,7 @@ public class RegenerationEffect extends SpellAbilityEffect {
|
||||
final Card host = sa.getHostCard();
|
||||
final Game game = host.getGame();
|
||||
for (Card c : getTargetCards(sa)) {
|
||||
if (!c.canBeShielded() || !c.isInPlay()) {
|
||||
continue;
|
||||
}
|
||||
// checks already done in ReplacementEffect
|
||||
|
||||
c.setDamage(0);
|
||||
c.setHasBeenDealtDeathtouchDamage(false);
|
||||
@@ -39,14 +33,9 @@ public class RegenerationEffect extends SpellAbilityEffect {
|
||||
game.fireEvent(new GameEventCardRegenerated(c));
|
||||
|
||||
if (host.isImmutable()) {
|
||||
c.subtractShield(host);
|
||||
c.decShieldCount();
|
||||
host.removeRemembered(c);
|
||||
}
|
||||
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(c);
|
||||
runParams.put(AbilityKey.Cause, host);
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Regenerated, runParams, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.util.List;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
@@ -14,7 +13,6 @@ import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
@@ -83,7 +81,6 @@ public class RevealEffect extends SpellAbilityEffect {
|
||||
game.getAction().reveal(revealed, p);
|
||||
}
|
||||
for (final Card c : revealed) {
|
||||
game.getTriggerHandler().runTrigger(TriggerType.Revealed, AbilityKey.mapFromCard(c), false);
|
||||
if (sa.hasParam("RememberRevealed")) {
|
||||
host.addRemembered(c);
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
private boolean hasBeenDealtExcessDamageThisTurn;
|
||||
|
||||
// regeneration
|
||||
private FCollection<Card> shields = new FCollection<>();
|
||||
private int shieldCount = 0;
|
||||
private int regeneratedThisTurn;
|
||||
|
||||
private int turnInZone;
|
||||
@@ -3230,28 +3230,22 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
|
||||
// shield = regeneration
|
||||
public final Iterable<Card> getShields() {
|
||||
return shields;
|
||||
}
|
||||
public final int getShieldCount() {
|
||||
return shields.size();
|
||||
return shieldCount;
|
||||
}
|
||||
|
||||
public final void addShield(final Card shield) {
|
||||
if (shields.add(shield)) {
|
||||
view.updateShieldCount(this);
|
||||
}
|
||||
public final void incShieldCount() {
|
||||
shieldCount++;
|
||||
view.updateShieldCount(this);
|
||||
}
|
||||
|
||||
public final void subtractShield(final Card shield) {
|
||||
if (shields.remove(shield)) {
|
||||
view.updateShieldCount(this);
|
||||
}
|
||||
public final void decShieldCount() {
|
||||
shieldCount--;
|
||||
view.updateShieldCount(this);
|
||||
}
|
||||
|
||||
public final void resetShield() {
|
||||
if (shields.isEmpty()) { return; }
|
||||
shields.clear();
|
||||
public final void resetShieldCount() {
|
||||
shieldCount = 0;
|
||||
view.updateShieldCount(this);
|
||||
}
|
||||
|
||||
@@ -3267,7 +3261,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
}
|
||||
|
||||
public final boolean canBeShielded() {
|
||||
return !hasKeyword("CARDNAME can't be regenerated.");
|
||||
return !StaticAbilityCantRegenerate.cantRegenerate(this);
|
||||
}
|
||||
|
||||
// is this "Card" supposed to be a token?
|
||||
@@ -6597,7 +6591,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
setHasBeenDealtDeathtouchDamage(false);
|
||||
setHasBeenDealtExcessDamageThisTurn(false);
|
||||
setRegeneratedThisTurn(0);
|
||||
resetShield();
|
||||
resetShieldCount();
|
||||
setBecameTargetThisTurn(false);
|
||||
setFoughtThisTurn(false);
|
||||
clearMustBlockCards();
|
||||
|
||||
@@ -2574,15 +2574,6 @@ public class CardFactoryUtil {
|
||||
|
||||
final ReplacementEffect re = makeEtbCounter(sb.toString(), card, intrinsic);
|
||||
|
||||
inst.addReplacement(re);
|
||||
} else if (keyword.equals("If CARDNAME would be destroyed, regenerate it.")) {
|
||||
String repeffstr = "Event$ Destroy | ActiveZones$ Battlefield | ValidCard$ Card.Self"
|
||||
+ " | Secondary$ True | Regeneration$ True | Description$ " + keyword;
|
||||
String effect = "DB$ Regeneration | Defined$ ReplacedCard";
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, host, intrinsic, card);
|
||||
SpellAbility sa = AbilityFactory.getAbility(effect, card);
|
||||
re.setOverridingAbility(sa);
|
||||
|
||||
inst.addReplacement(re);
|
||||
}
|
||||
|
||||
@@ -2639,30 +2630,6 @@ public class CardFactoryUtil {
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(rep, host, intrinsic, card);
|
||||
inst.addReplacement(re);
|
||||
}
|
||||
else if (keyword.startsWith("If CARDNAME would be put into a graveyard "
|
||||
+ "from anywhere, reveal CARDNAME and shuffle it into its owner's library instead.")) {
|
||||
StringBuilder sb = new StringBuilder("Event$ Moved | Destination$ Graveyard | ValidCard$ Card.Self ");
|
||||
|
||||
// to show it on Nexus
|
||||
if (host.isPermanent()) {
|
||||
sb.append("| Secondary$ True");
|
||||
}
|
||||
sb.append("| Description$ ").append(keyword);
|
||||
|
||||
String ab = "DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Library | Defined$ ReplacedCard | Reveal$ True | Shuffle$ True";
|
||||
|
||||
SpellAbility sa = AbilityFactory.getAbility(ab, card);
|
||||
|
||||
if (!intrinsic) {
|
||||
sa.setIntrinsic(false);
|
||||
}
|
||||
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(sb.toString(), host, intrinsic, card);
|
||||
|
||||
re.setOverridingAbility(sa);
|
||||
|
||||
inst.addReplacement(re);
|
||||
}
|
||||
|
||||
if (keyword.equals("CARDNAME enters the battlefield tapped.")) {
|
||||
String effect = "DB$ Tap | Defined$ Self | ETB$ True "
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package forge.game.staticability;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class StaticAbilityCantRegenerate {
|
||||
|
||||
static String MODE = "CantRegenerate";
|
||||
|
||||
public static boolean cantRegenerate(final Card card) {
|
||||
final Game game = card.getGame();
|
||||
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
|
||||
for (final StaticAbility stAb : ca.getStaticAbilities()) {
|
||||
if (!stAb.checkConditions(MODE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (applyCantRegenerateAbility(stAb, card)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean applyCantRegenerateAbility(final StaticAbility stAb, final Card card) {
|
||||
if (!stAb.matchesValidParam("ValidCard", card)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.Map;
|
||||
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Localizer;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Trigger_Destroyed class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: TriggerDestroyed.java 17802 2012-10-31 08:05:14Z Max mtg $
|
||||
*/
|
||||
public class TriggerRegenerated extends Trigger {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for Trigger_Destroyed.
|
||||
* </p>
|
||||
*
|
||||
* @param params
|
||||
* a {@link java.util.HashMap} object.
|
||||
* @param host
|
||||
* a {@link forge.game.card.Card} object.
|
||||
* @param intrinsic
|
||||
* the intrinsic
|
||||
*/
|
||||
public TriggerRegenerated(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) {
|
||||
if (!matchesValidParam("ValidCause", runParams.get(AbilityKey.Cause))) {
|
||||
return false;
|
||||
}
|
||||
if (!matchesValidParam("ValidCard", runParams.get(AbilityKey.Card))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Object> runParams) {
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card, AbilityKey.Cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImportantStackObjects(SpellAbility sa) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Localizer.getInstance().getMessage("lblRegenerated")).append(": ").append(sa.getTriggeringObject(AbilityKey.Card));
|
||||
//sb.append("Destroyer: ").append(sa.getTriggeringObject("Causer"));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package forge.game.trigger;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Localizer;
|
||||
|
||||
@Deprecated
|
||||
public class TriggerRevealed extends Trigger {
|
||||
|
||||
public TriggerRevealed(Map<String, String> params, Card host, boolean intrinsic) {
|
||||
super(params, host, intrinsic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performTest(Map<AbilityKey, Object> runParams) {
|
||||
if (!matchesValidParam("ValidCard", runParams.get(AbilityKey.Card))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTriggeringObjects(SpellAbility sa, Map<AbilityKey, Object> runParams) {
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImportantStackObjects(SpellAbility sa) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Localizer.getInstance().getMessage("lblRevealed")).append(": ").append(sa.getTriggeringObject(AbilityKey.Card));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,184 +1,182 @@
|
||||
package forge.game.trigger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.card.Card;
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public enum TriggerType {
|
||||
Abandoned(TriggerAbandoned.class),
|
||||
AbilityCast(TriggerSpellAbilityCastOrCopy.class),
|
||||
AbilityResolves(TriggerAbilityResolves.class),
|
||||
AbilityTriggered(TriggerAbilityTriggered.class),
|
||||
Adapt(TriggerAdapt.class),
|
||||
Always(TriggerAlways.class),
|
||||
Attached(TriggerAttached.class),
|
||||
AttackerBlocked(TriggerAttackerBlocked.class),
|
||||
AttackerBlockedOnce(TriggerAttackerBlockedOnce.class),
|
||||
AttackerBlockedByCreature(TriggerAttackerBlockedByCreature.class),
|
||||
AttackersDeclared(TriggerAttackersDeclared.class),
|
||||
AttackersDeclaredOneTarget(TriggerAttackersDeclared.class),
|
||||
AttackerUnblocked(TriggerAttackerUnblocked.class),
|
||||
AttackerUnblockedOnce(TriggerAttackerUnblockedOnce.class),
|
||||
Attacks(TriggerAttacks.class),
|
||||
BecomeMonarch(TriggerBecomeMonarch.class),
|
||||
BecomeMonstrous(TriggerBecomeMonstrous.class),
|
||||
BecomeRenowned(TriggerBecomeRenowned.class),
|
||||
BecomesCrewed(TriggerBecomesCrewed.class),
|
||||
BecomesTarget(TriggerBecomesTarget.class),
|
||||
BecomesTargetOnce(TriggerBecomesTargetOnce.class),
|
||||
BlockersDeclared(TriggerBlockersDeclared.class),
|
||||
Blocks(TriggerBlocks.class),
|
||||
Championed(TriggerChampioned.class),
|
||||
ChangesController(TriggerChangesController.class),
|
||||
ChangesZone(TriggerChangesZone.class),
|
||||
ChangesZoneAll(TriggerChangesZoneAll.class),
|
||||
ChaosEnsues(TriggerChaosEnsues.class),
|
||||
Clashed(TriggerClashed.class),
|
||||
ClassLevelGained(TriggerClassLevelGained.class),
|
||||
ConjureAll(TriggerConjureAll.class),
|
||||
CounterAdded(TriggerCounterAdded.class),
|
||||
CounterAddedOnce(TriggerCounterAddedOnce.class),
|
||||
CounterPlayerAddedAll(TriggerCounterPlayerAddedAll.class),
|
||||
CounterAddedAll(TriggerCounterAddedAll.class),
|
||||
Countered(TriggerCountered.class),
|
||||
CounterRemoved(TriggerCounterRemoved.class),
|
||||
CounterRemovedOnce(TriggerCounterRemovedOnce.class),
|
||||
Crewed(TriggerCrewed.class),
|
||||
Cycled(TriggerCycled.class),
|
||||
DamageAll(TriggerDamageAll.class),
|
||||
DamageDealtOnce(TriggerDamageDealtOnce.class),
|
||||
DamageDone(TriggerDamageDone.class),
|
||||
DamageDoneOnce(TriggerDamageDoneOnce.class),
|
||||
DamageDoneOnceByController(TriggerDamageDoneOnceByController.class),
|
||||
DamagePrevented(TriggerDamagePrevented.class),
|
||||
DamagePreventedOnce(TriggerDamagePreventedOnce.class),
|
||||
DayTimeChanges (TriggerDayTimeChanges.class),
|
||||
Destroyed(TriggerDestroyed.class),
|
||||
Devoured(TriggerDevoured.class),
|
||||
Discarded(TriggerDiscarded.class),
|
||||
DiscardedAll(TriggerDiscardedAll.class),
|
||||
Drawn(TriggerDrawn.class),
|
||||
DungeonCompleted(TriggerCompletedDungeon.class),
|
||||
Evolved(TriggerEvolved.class),
|
||||
ExcessDamage(TriggerExcessDamage.class),
|
||||
Enlisted(TriggerEnlisted.class),
|
||||
Exerted(TriggerExerted.class),
|
||||
Exiled(TriggerExiled.class),
|
||||
Exploited(TriggerExploited.class),
|
||||
Explores(TriggerExplores.class),
|
||||
Fight(TriggerFight.class),
|
||||
FightOnce(TriggerFightOnce.class),
|
||||
FlippedCoin(TriggerFlippedCoin.class),
|
||||
Foretell(TriggerForetell.class),
|
||||
Immediate(TriggerImmediate.class),
|
||||
Investigated(TriggerInvestigated.class),
|
||||
IsForetold(TriggerIsForetold.class),
|
||||
LandPlayed(TriggerLandPlayed.class),
|
||||
LifeGained(TriggerLifeGained.class),
|
||||
LifeLost(TriggerLifeLost.class),
|
||||
LifeLostAll(TriggerLifeLostAll.class),
|
||||
LosesGame(TriggerLosesGame.class),
|
||||
ManaAdded(TriggerManaAdded.class),
|
||||
MilledAll(TriggerMilledAll.class),
|
||||
Mutates(TriggerMutates.class),
|
||||
NewGame(TriggerNewGame.class),
|
||||
PayCumulativeUpkeep(TriggerPayCumulativeUpkeep.class),
|
||||
PayEcho(TriggerPayEcho.class),
|
||||
PayLife(TriggerPayLife.class),
|
||||
Phase(TriggerPhase.class),
|
||||
PhaseIn(TriggerPhaseIn.class),
|
||||
PhaseOut(TriggerPhaseOut.class),
|
||||
PlanarDice(TriggerPlanarDice.class),
|
||||
PlaneswalkedFrom(TriggerPlaneswalkedFrom.class),
|
||||
PlaneswalkedTo(TriggerPlaneswalkedTo.class),
|
||||
Proliferate(TriggerProliferate.class),
|
||||
Regenerated(TriggerRegenerated.class),
|
||||
Revealed(TriggerRevealed.class),
|
||||
RingTemptsYou(TriggerRingTemptsYou.class),
|
||||
RolledDie(TriggerRolledDie.class),
|
||||
RolledDieOnce(TriggerRolledDieOnce.class),
|
||||
RoomEntered(TriggerEnteredRoom.class),
|
||||
Sacrificed(TriggerSacrificed.class),
|
||||
Scry(TriggerScry.class),
|
||||
SearchedLibrary(TriggerSearchedLibrary.class),
|
||||
SeekAll(TriggerSeekAll.class),
|
||||
SetInMotion(TriggerSetInMotion.class),
|
||||
Shuffled(TriggerShuffled.class),
|
||||
Specializes(TriggerSpecializes.class),
|
||||
SpellAbilityCast(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellAbilityCopy(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellCast(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellCastOrCopy(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellCopy(TriggerSpellAbilityCastOrCopy.class),
|
||||
Surveil(TriggerSurveil.class),
|
||||
TakesInitiative(TriggerTakesInitiative.class),
|
||||
Taps(TriggerTaps.class),
|
||||
TapsForMana(TriggerTapsForMana.class),
|
||||
TokenCreated(TriggerTokenCreated.class),
|
||||
TokenCreatedOnce(TriggerTokenCreatedOnce.class),
|
||||
Trains(TriggerTrains.class),
|
||||
Transformed(TriggerTransformed.class),
|
||||
TurnBegin(TriggerTurnBegin.class),
|
||||
TurnFaceUp(TriggerTurnFaceUp.class),
|
||||
Unattach(TriggerUnattach.class),
|
||||
Untaps(TriggerUntaps.class),
|
||||
Vote(TriggerVote.class);
|
||||
|
||||
private final Constructor<? extends Trigger> constructor;
|
||||
|
||||
TriggerType(Class<? extends Trigger> clasz) {
|
||||
constructor = findConstructor(clasz);
|
||||
}
|
||||
|
||||
private static Constructor<? extends Trigger> findConstructor(Class<? extends Trigger> clasz) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<? extends Trigger>[] cc = (Constructor<? extends Trigger>[]) clasz.getDeclaredConstructors();
|
||||
for (Constructor<? extends Trigger> c : cc) {
|
||||
Class<?>[] pp = c.getParameterTypes();
|
||||
if (pp[0].isAssignableFrom(Map.class)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No constructor found that would take Map as 1st parameter in class " + clasz.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static TriggerType smartValueOf(String value) {
|
||||
final String valToCompate = value.trim();
|
||||
for (final TriggerType v : TriggerType.values()) {
|
||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Element " + value + " not found in TriggerType enum");
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param mapParams
|
||||
* @param host
|
||||
* @param intrinsic
|
||||
* @return
|
||||
*/
|
||||
public Trigger createTrigger(Map<String, String> mapParams, Card host, boolean intrinsic) {
|
||||
try {
|
||||
Trigger res = constructor.newInstance(mapParams, host, intrinsic);
|
||||
res.setMode(this);
|
||||
return res;
|
||||
} catch (IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.game.trigger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.card.Card;
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public enum TriggerType {
|
||||
Abandoned(TriggerAbandoned.class),
|
||||
AbilityCast(TriggerSpellAbilityCastOrCopy.class),
|
||||
AbilityResolves(TriggerAbilityResolves.class),
|
||||
AbilityTriggered(TriggerAbilityTriggered.class),
|
||||
Adapt(TriggerAdapt.class),
|
||||
Always(TriggerAlways.class),
|
||||
Attached(TriggerAttached.class),
|
||||
AttackerBlocked(TriggerAttackerBlocked.class),
|
||||
AttackerBlockedOnce(TriggerAttackerBlockedOnce.class),
|
||||
AttackerBlockedByCreature(TriggerAttackerBlockedByCreature.class),
|
||||
AttackersDeclared(TriggerAttackersDeclared.class),
|
||||
AttackersDeclaredOneTarget(TriggerAttackersDeclared.class),
|
||||
AttackerUnblocked(TriggerAttackerUnblocked.class),
|
||||
AttackerUnblockedOnce(TriggerAttackerUnblockedOnce.class),
|
||||
Attacks(TriggerAttacks.class),
|
||||
BecomeMonarch(TriggerBecomeMonarch.class),
|
||||
BecomeMonstrous(TriggerBecomeMonstrous.class),
|
||||
BecomeRenowned(TriggerBecomeRenowned.class),
|
||||
BecomesCrewed(TriggerBecomesCrewed.class),
|
||||
BecomesTarget(TriggerBecomesTarget.class),
|
||||
BecomesTargetOnce(TriggerBecomesTargetOnce.class),
|
||||
BlockersDeclared(TriggerBlockersDeclared.class),
|
||||
Blocks(TriggerBlocks.class),
|
||||
Championed(TriggerChampioned.class),
|
||||
ChangesController(TriggerChangesController.class),
|
||||
ChangesZone(TriggerChangesZone.class),
|
||||
ChangesZoneAll(TriggerChangesZoneAll.class),
|
||||
ChaosEnsues(TriggerChaosEnsues.class),
|
||||
Clashed(TriggerClashed.class),
|
||||
ClassLevelGained(TriggerClassLevelGained.class),
|
||||
ConjureAll(TriggerConjureAll.class),
|
||||
CounterAdded(TriggerCounterAdded.class),
|
||||
CounterAddedOnce(TriggerCounterAddedOnce.class),
|
||||
CounterPlayerAddedAll(TriggerCounterPlayerAddedAll.class),
|
||||
CounterAddedAll(TriggerCounterAddedAll.class),
|
||||
Countered(TriggerCountered.class),
|
||||
CounterRemoved(TriggerCounterRemoved.class),
|
||||
CounterRemovedOnce(TriggerCounterRemovedOnce.class),
|
||||
Crewed(TriggerCrewed.class),
|
||||
Cycled(TriggerCycled.class),
|
||||
DamageAll(TriggerDamageAll.class),
|
||||
DamageDealtOnce(TriggerDamageDealtOnce.class),
|
||||
DamageDone(TriggerDamageDone.class),
|
||||
DamageDoneOnce(TriggerDamageDoneOnce.class),
|
||||
DamageDoneOnceByController(TriggerDamageDoneOnceByController.class),
|
||||
DamagePrevented(TriggerDamagePrevented.class),
|
||||
DamagePreventedOnce(TriggerDamagePreventedOnce.class),
|
||||
DayTimeChanges (TriggerDayTimeChanges.class),
|
||||
Destroyed(TriggerDestroyed.class),
|
||||
Devoured(TriggerDevoured.class),
|
||||
Discarded(TriggerDiscarded.class),
|
||||
DiscardedAll(TriggerDiscardedAll.class),
|
||||
Drawn(TriggerDrawn.class),
|
||||
DungeonCompleted(TriggerCompletedDungeon.class),
|
||||
Evolved(TriggerEvolved.class),
|
||||
ExcessDamage(TriggerExcessDamage.class),
|
||||
Enlisted(TriggerEnlisted.class),
|
||||
Exerted(TriggerExerted.class),
|
||||
Exiled(TriggerExiled.class),
|
||||
Exploited(TriggerExploited.class),
|
||||
Explores(TriggerExplores.class),
|
||||
Fight(TriggerFight.class),
|
||||
FightOnce(TriggerFightOnce.class),
|
||||
FlippedCoin(TriggerFlippedCoin.class),
|
||||
Foretell(TriggerForetell.class),
|
||||
Immediate(TriggerImmediate.class),
|
||||
Investigated(TriggerInvestigated.class),
|
||||
IsForetold(TriggerIsForetold.class),
|
||||
LandPlayed(TriggerLandPlayed.class),
|
||||
LifeGained(TriggerLifeGained.class),
|
||||
LifeLost(TriggerLifeLost.class),
|
||||
LifeLostAll(TriggerLifeLostAll.class),
|
||||
LosesGame(TriggerLosesGame.class),
|
||||
ManaAdded(TriggerManaAdded.class),
|
||||
MilledAll(TriggerMilledAll.class),
|
||||
Mutates(TriggerMutates.class),
|
||||
NewGame(TriggerNewGame.class),
|
||||
PayCumulativeUpkeep(TriggerPayCumulativeUpkeep.class),
|
||||
PayEcho(TriggerPayEcho.class),
|
||||
PayLife(TriggerPayLife.class),
|
||||
Phase(TriggerPhase.class),
|
||||
PhaseIn(TriggerPhaseIn.class),
|
||||
PhaseOut(TriggerPhaseOut.class),
|
||||
PlanarDice(TriggerPlanarDice.class),
|
||||
PlaneswalkedFrom(TriggerPlaneswalkedFrom.class),
|
||||
PlaneswalkedTo(TriggerPlaneswalkedTo.class),
|
||||
Proliferate(TriggerProliferate.class),
|
||||
RingTemptsYou(TriggerRingTemptsYou.class),
|
||||
RolledDie(TriggerRolledDie.class),
|
||||
RolledDieOnce(TriggerRolledDieOnce.class),
|
||||
RoomEntered(TriggerEnteredRoom.class),
|
||||
Sacrificed(TriggerSacrificed.class),
|
||||
Scry(TriggerScry.class),
|
||||
SearchedLibrary(TriggerSearchedLibrary.class),
|
||||
SeekAll(TriggerSeekAll.class),
|
||||
SetInMotion(TriggerSetInMotion.class),
|
||||
Shuffled(TriggerShuffled.class),
|
||||
Specializes(TriggerSpecializes.class),
|
||||
SpellAbilityCast(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellAbilityCopy(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellCast(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellCastOrCopy(TriggerSpellAbilityCastOrCopy.class),
|
||||
SpellCopy(TriggerSpellAbilityCastOrCopy.class),
|
||||
Surveil(TriggerSurveil.class),
|
||||
TakesInitiative(TriggerTakesInitiative.class),
|
||||
Taps(TriggerTaps.class),
|
||||
TapsForMana(TriggerTapsForMana.class),
|
||||
TokenCreated(TriggerTokenCreated.class),
|
||||
TokenCreatedOnce(TriggerTokenCreatedOnce.class),
|
||||
Trains(TriggerTrains.class),
|
||||
Transformed(TriggerTransformed.class),
|
||||
TurnBegin(TriggerTurnBegin.class),
|
||||
TurnFaceUp(TriggerTurnFaceUp.class),
|
||||
Unattach(TriggerUnattach.class),
|
||||
Untaps(TriggerUntaps.class),
|
||||
Vote(TriggerVote.class);
|
||||
|
||||
private final Constructor<? extends Trigger> constructor;
|
||||
|
||||
TriggerType(Class<? extends Trigger> clasz) {
|
||||
constructor = findConstructor(clasz);
|
||||
}
|
||||
|
||||
private static Constructor<? extends Trigger> findConstructor(Class<? extends Trigger> clasz) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<? extends Trigger>[] cc = (Constructor<? extends Trigger>[]) clasz.getDeclaredConstructors();
|
||||
for (Constructor<? extends Trigger> c : cc) {
|
||||
Class<?>[] pp = c.getParameterTypes();
|
||||
if (pp[0].isAssignableFrom(Map.class)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No constructor found that would take Map as 1st parameter in class " + clasz.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static TriggerType smartValueOf(String value) {
|
||||
final String valToCompate = value.trim();
|
||||
for (final TriggerType v : TriggerType.values()) {
|
||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Element " + value + " not found in TriggerType enum");
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param mapParams
|
||||
* @param host
|
||||
* @param intrinsic
|
||||
* @return
|
||||
*/
|
||||
public Trigger createTrigger(Map<String, String> mapParams, Card host, boolean intrinsic) {
|
||||
try {
|
||||
Trigger res = constructor.newInstance(mapParams, host, intrinsic);
|
||||
res.setMode(this);
|
||||
return res;
|
||||
} catch (IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,10 @@ public class WrappedAbility extends Ability {
|
||||
ApiType.SacrificeAll,
|
||||
ApiType.Pump,
|
||||
|
||||
ApiType.Regenerate, // Updated
|
||||
ApiType.RegenerateAll, // No Triggered
|
||||
ApiType.Regeneration, // Replacement Effect only
|
||||
|
||||
ApiType.DelayedTrigger
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user