Ring tempts you (#3453)

* Ring tempts you WIP

* add ring triggers

* Update RingTemptsYouEffect.java

* Add files via upload

* Update TriggerRingbearerChosen.java

* Update token-images.txt

* Update TrackableProperty.java

* Update CardView.java

* Update CardRenderer.java

* Update RingTemptsYouEffect.java

fix crash

* Update Card.java

* Update CardView.java

* Update TrackableProperty.java

* Update StaticAbilityContinuous.java

* Update StaticEffect.java

* Update RingTemptsYouEffect.java

* update sprite_manaicons.png

* Update FSkinProp.java

* Update FSkinImage.java

* Update CardFaceSymbols.java

* Update CardRenderer.java

* update trigger

* update desktop symbol, add aragorn company leader

* update cleanup, add bilbo, add birthday escape

* update cleanup

* add 3 cards

* add five cards

* add two cards

* update aragorn,update bombadil, add two cards

* add ten cards

* Update horses_of_the_bruinen.txt

* add dunedain rangers + cleanup

* Update gollums_bite.txt

* update cleanup

* add six cards

* delete unnecessary file

* Update rangers_firebrand.txt

* add two cards, add RingTemptedYou playerproperty

* update frodo, add three cards

* update sauron, samwise, add two cards

* Update sauron_the_dark_lord.txt

* update validplayer

* add six cards

* update smeagol

* update sauron ransom two piles

* add four cards

* add three cards

* update card scripts

* Update war_of_the_last_alliance.txt

* update scripts, update ringbearer

* update CardDetailUtil

* remove unused param

* Update affected

* remove unnecesary variables

* update

* update scripts

* update RingTemptsYouEffect

* fix cantblockby RingTemptsYouEffect.java

* The Ring: use numTemptYou for RingLevel

* Update dunedain_rangers.txt

* Update jaces_defeat.txt

* update lord of the nazgul

* fix theRing CardView

* update ringEffect, update translation

* update translation

* update gamestate

* replace switch with if else

* fix effect

* update gamestate, translation

* update restartgameeffect, remove unneeded clearRingBearer

---------

Co-authored-by: Anthony Calosa <anthonycalosa@gmail.com>
Co-authored-by: tool4ever <therealtoolkit@hotmail.com>
Co-authored-by: Hans Mackowiak <hanmac@gmx.de>
This commit is contained in:
Chris H
2023-07-26 13:07:41 -04:00
committed by GitHub
parent 69748ab0fb
commit abb2ff3cdf
106 changed files with 1038 additions and 231 deletions

View File

@@ -1012,6 +1012,9 @@ public class GameAction {
partner.updateStateForView();
}
// run Game Commands early
c.runChangeControllerCommands();
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
oldBattlefield.remove(c);
@@ -1027,7 +1030,7 @@ public class GameAction {
game.getTriggerHandler().runTrigger(TriggerType.ChangesController, runParams, false);
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
c.runChangeControllerCommands();
}
// Temporarily disable (if mode = true) actively checking static abilities.

View File

@@ -3501,6 +3501,10 @@ public class AbilityUtils {
if (value.equals("DungeonsCompleted")) {
return doXMath(player.getCompletedDungeons().size(), m, source, ctb);
}
if (value.equals("RingTemptedYou")) {
return doXMath(player.getNumRingTemptedYou(), m, source, ctb);
}
if (value.startsWith("DungeonCompletedNamed")) {
String [] full = value.split("_");
String name = full[1];

View File

@@ -158,6 +158,8 @@ public enum ApiType {
Reveal (RevealEffect.class),
RevealHand (RevealHandEffect.class),
ReverseTurnOrder (ReverseTurnOrderEffect.class),
RingTemptsYou (RingTemptsYouEffect.class),
RollDice (RollDiceEffect.class),
RollPlanarDice (RollPlanarDiceEffect.class),
RunChaos (RunChaosEffect.class),

View File

@@ -587,11 +587,15 @@ public class CountersPutEffect extends SpellAbilityEffect {
GameEntityCounterTable table = new GameEntityCounterTable();
if (sa.hasParam("TriggeredCounterMap")) {
Integer counterMapValue = null;
if (sa.hasParam("CounterMapValues")) {
counterMapValue = Integer.valueOf(sa.getParam("CounterMapValues"));
}
@SuppressWarnings("unchecked")
Map<CounterType, Integer> counterMap = (Map<CounterType, Integer>) sa
.getTriggeringObject(AbilityKey.CounterMap);
for (Map.Entry<CounterType, Integer> e : counterMap.entrySet()) {
resolvePerType(sa, placer, e.getKey(), e.getValue(), table, false);
resolvePerType(sa, placer, e.getKey(), counterMapValue == null ? e.getValue() : counterMapValue, table, false);
}
} else if (sa.hasParam("SharedKeywords")) {
List<String> keywords = Arrays.asList(sa.getParam("SharedKeywords").split(" & "));

View File

@@ -20,12 +20,13 @@ import forge.game.zone.ZoneType;
import forge.util.Lang;
import forge.util.Localizer;
import forge.util.MyRandom;
import org.apache.commons.lang3.StringUtils;
public class DigUntilEffect extends SpellAbilityEffect {
/* (non-Javadoc)
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
*/
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
*/
@Override
protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder();
@@ -33,7 +34,9 @@ public class DigUntilEffect extends SpellAbilityEffect {
String desc = sa.getParamOrDefault("ValidDescription", "Card");
int untilAmount = 1;
boolean isNumeric = true;
if (sa.hasParam("Amount")) {
isNumeric = StringUtils.isNumeric(sa.getParam("Amount"));
untilAmount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa);
}
@@ -42,7 +45,8 @@ public class DigUntilEffect extends SpellAbilityEffect {
final ZoneType revealed = ZoneType.smartValueOf(sa.getParam("RevealedDestination"));
sb.append(ZoneType.Exile.equals(revealed) ? "exiles cards from their library until they exile " :
"reveals cards from their library until revealing ");
sb.append(Lang.nounWithNumeralExceptOne(untilAmount, desc + " card"));
String noun = "Card".equals(desc) ? " card" : desc + " card";
sb.append(isNumeric ? Lang.nounWithNumeralExceptOne(untilAmount, noun) : "X " + noun);
if (untilAmount != 1) {
sb.append("s");
}
@@ -57,19 +61,30 @@ public class DigUntilEffect extends SpellAbilityEffect {
final ZoneType found = ZoneType.smartValueOf(sa.getParam("FoundDestination"));
if (found != null) {
sb.append(untilAmount > 1 ? "those cards" : "that card");
sb.append(untilAmount > 1 || !isNumeric ? "those cards" : "that card");
sb.append(" ");
if (ZoneType.Hand.equals(found)) {
sb.append("into their hand ");
}
if (ZoneType.Battlefield.equals(found)) {
sb.append("onto the battlefield ");
if (sa.hasParam("Tapped"))
sb.append("tapped ");
}
if (ZoneType.Graveyard.equals(revealed)) {
sb.append("and all other cards into their graveyard.");
}
if (ZoneType.Exile.equals(revealed)) {
sb.append("and exile all other cards revealed this way.");
}
if (ZoneType.Library.equals(revealed)) {
int revealedLibPos = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("RevealedLibraryPosition"), sa);
sb.append("and the rest on ").append(revealedLibPos < 0 ? "the bottom " : "on top ");
sb.append("of their library").append(sa.hasParam("RevealRandomOrder") ? " in a random order." : ".");
}
} else if (revealed != null) {
if (ZoneType.Hand.equals(revealed)) {
sb.append("all cards revealed this way into their hand");

View File

@@ -70,6 +70,9 @@ public class RestartGameEffect extends SpellAbilityEffect {
p.setLifeLostLastTurn(0);
p.resetCommanderStats();
p.resetCompletedDungeons();
p.resetRingTemptedYou();
p.clearRingBearer();
p.clearTheRing();
p.setBlessing(false);
p.clearController();

View File

@@ -0,0 +1,60 @@
package forge.game.ability.effects;
import forge.GameCommand;
import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.util.Localizer;
import java.util.Map;
public class RingTemptsYouEffect extends EffectEffect {
@Override
protected String getStackDescription(SpellAbility sa) {
return Localizer.getInstance().getMessage("lblTheRingTempts", sa.getActivatingPlayer());
}
@Override
public void resolve(SpellAbility sa) {
Player p = sa.getActivatingPlayer();
Game game = p.getGame();
Card card = sa.getHostCard();
if (p.getTheRing() == null)
p.createTheRing(card);
//increment ring tempted you for property
p.incrementRingTemptedYou();
p.setRingLevel(p.getNumRingTemptedYou());
// Then choose a ring-bearer (You may keep the same one). Auto pick if <2 choices.
CardCollection creatures = p.getCreaturesInPlay();
Card ringBearer = p.getController().chooseSingleEntityForEffect(creatures, sa, Localizer.getInstance().getMessageorUseDefault("lblChooseRingBearer", "Choose your Ring-bearer"), false, null);
p.setRingBearer(ringBearer);
// 701.52a That creature becomes your Ring-bearer until another player gains control of it.
if (ringBearer != null) {
GameCommand loseCommand = new GameCommand() {
private static final long serialVersionUID = 1L;
@Override
public void run() {
if (ringBearer.isRingBearer()) {
p.clearRingBearer();
}
}
};
ringBearer.addChangeControllerCommand(loseCommand);
ringBearer.addLeavesPlayCommand(loseCommand);
}
// Run triggers
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(p);
runParams.put(AbilityKey.Card, ringBearer);
game.getTriggerHandler().runTrigger(TriggerType.RingTemptsYou, runParams, false);
}
}

View File

@@ -30,7 +30,7 @@ public class TwoPilesEffect extends SpellAbilityEffect {
sb.append("Separate all ").append(valid).append(" cards ");
sb.append(Lang.joinHomogenous(getTargetPlayers(sa)));
sb.append("controls into two piles.");
sb.append(" controls into two piles.");
return sb.toString();
}

View File

@@ -209,7 +209,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private boolean copiedSpell = false;
private boolean unearthed;
private boolean ringbearer;
private boolean monstrous;
private boolean renowned;
@@ -225,7 +225,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private int timesCrewedThisTurn = 0;
private int classLevel = 1;
private long bestowTimestamp = -1;
private long transformedTimestamp = 0;
private long mutatedTimestamp = -1;
@@ -6032,6 +6031,16 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public boolean wasDiscarded() { return discarded; }
public void setDiscarded(boolean state) { discarded = state; }
public final boolean isRingBearer() {
return ringbearer;
}
public final void setRingBearer(final boolean ringbearer0) {
ringbearer = ringbearer0;
view.updateRingBearer(this);
}
public final void clearRingBearer() {
setRingBearer(false);
}
public final boolean isMonstrous() {
return monstrous;
}

View File

@@ -167,6 +167,10 @@ public class CardProperty {
if (!card.isAdventureCard()) {
return false;
}
} else if (property.equals("IsRingbearer")) {
if (!card.isRingBearer()) {
return false;
}
} else if (property.equals("IsTriggerRemembered")) {
boolean found = false;
for (Object o : spellAbility.getTriggerRemembered()) {

View File

@@ -466,6 +466,15 @@ public class CardView extends GameEntityView {
set(TrackableProperty.ClassLevel, c.getClassLevel());
}
public int getRingLevel() {
return get(TrackableProperty.RingLevel);
}
void updateRingLevel(Card c) {
Player p = c.getController();
if (p != null && p.getTheRing() == c)
set(TrackableProperty.RingLevel, p.getNumRingTemptedYou());
}
private String getRemembered() {
return get(TrackableProperty.Remembered);
}
@@ -925,6 +934,7 @@ public class CardView extends GameEntityView {
updateZoneText(c);
updateDamage(c);
updateSpecialize(c);
updateRingLevel(c);
if (c.getIntensity(false) > 0) {
updateIntensity(c);
@@ -1064,6 +1074,14 @@ public class CardView extends GameEntityView {
set(TrackableProperty.BlockAny, c.canBlockAny());
}
public boolean isRingBearer() {
return get(TrackableProperty.IsRingBearer);
}
void updateRingBearer(Card c) {
set(TrackableProperty.IsRingBearer, c.isRingBearer());
}
Set<String> getCantHaveKeyword() {
return get(TrackableProperty.CantHaveKeyword);
}

View File

@@ -34,6 +34,7 @@ import java.util.Set;
import java.util.SortedSet;
import forge.game.event.*;
import forge.game.spellability.AbilitySub;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
@@ -166,12 +167,14 @@ public class Player extends GameEntity implements Comparable<Player> {
private int startingHandSize = 7;
private boolean unlimitedHandSize = false;
private Card lastDrawnCard;
private Card ringBearer, theRing;
private String namedCard = "";
private String namedCard2 = "";
private int simultaneousDamage = 0;
private int lastTurnNr = 0;
private int numRingTemptedYou = 0;
private final Map<String, FCollection<String>> notes = Maps.newHashMap();
private final Map<String, Integer> notedNum = Maps.newHashMap();
@@ -1829,7 +1832,28 @@ public class Player extends GameEntity implements Comparable<Player> {
lastDrawnCard = c;
return lastDrawnCard;
}
public final Card getRingBearer() {
return ringBearer;
}
public final Card getTheRing() {
return theRing;
}
public final void clearTheRing() {
theRing = null;
}
public final void setRingBearer(Card bearer) {
if (bearer == null)
return;
clearRingBearer();
ringBearer = bearer;
ringBearer.setRingBearer(true);
}
public void clearRingBearer() {
if (ringBearer == null)
return;
ringBearer.setRingBearer(false);
ringBearer = null;
}
public final String getNamedCard() {
return namedCard;
}
@@ -1927,6 +1951,19 @@ public class Player extends GameEntity implements Comparable<Player> {
completedDungeons.clear();
}
public final int getNumRingTemptedYou() {
return numRingTemptedYou;
}
public final void incrementRingTemptedYou() {
numRingTemptedYou++;
}
public final void setNumRingTemptedYou(int value) {
numRingTemptedYou = value;
}
public final void resetRingTemptedYou() {
numRingTemptedYou = 0;
}
public final List<Card> getPlaneswalkedToThisTurn() {
return planeswalkedToThisTurn;
}
@@ -3116,7 +3153,72 @@ public class Player extends GameEntity implements Comparable<Player> {
eff.addStaticAbility(mayBePlayedAbility);
return eff;
}
public void createTheRing(Card host) {
final PlayerZone com = getZone(ZoneType.Command);
if (theRing == null) {
theRing = new Card(game.nextCardId(), null, game);
theRing.setOwner(this);
theRing.setImmutable(true);
String image = ImageKeys.getTokenKey("the_ring");
if (host != null) {
theRing.setImageKey("t:the_ring_" + host.getSetCode().toLowerCase());
theRing.setSetCode(host.getSetCode());
} else {
theRing.setImageKey(image);
}
theRing.setName("The Ring");
theRing.updateStateForView();
com.add(theRing);
this.updateZoneForView(com);
}
}
public void setRingLevel(int level) {
if (getTheRing() == null)
createTheRing(null);
if (level == 1) {
String legendary = "Mode$ Continuous | EffectZone$ Command | Affected$ Card.YouCtrl+IsRingbearer | AddType$ Legendary | Description$ Your Ring-bearer is legendary.";
String cantBeBlocked = "Mode$ CantBlockBy | EffectZone$ Command | ValidAttacker$ Card.YouCtrl+IsRingbearer | ValidBlockerRelative$ Creature.powerGTX | Description$ Your Ring-bearer can't be blocked by creatures with greater power.";
getTheRing().addStaticAbility(legendary);
StaticAbility st = getTheRing().addStaticAbility(cantBeBlocked);
st.setSVar("X", "Count$CardPower");
} else if (level == 2) {
final String attackTrig = "Mode$ Attacks | ValidCard$ Card.YouCtrl+IsRingbearer | TriggerDescription$ Whenever your ring-bearer attacks, draw a card, then discard a card. | TriggerZones$ Command";
final String drawEffect = "DB$ Draw | Defined$ You | NumCards$ 1";
final String discardEffect = "DB$ Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose";
final Trigger attackTrigger = TriggerHandler.parseTrigger(attackTrig, getTheRing(), true);
SpellAbility drawExecute = AbilityFactory.getAbility(drawEffect, getTheRing());
AbilitySub discardExecute = (AbilitySub) AbilityFactory.getAbility(discardEffect, getTheRing());
drawExecute.setSubAbility(discardExecute);
attackTrigger.setOverridingAbility(drawExecute);
getTheRing().addTrigger(attackTrigger);
} else if (level == 3) {
final String becomesBlockedTrig = "Mode$ AttackerBlockedByCreature | ValidCard$ Card.YouCtrl+IsRingbearer| ValidBlocker$ Creature | TriggerZones$ Command | TriggerDescription$ Whenever your Ring-bearer becomes blocked a creature, that creature's controller sacrifices it at the end of combat.";
final String endOfCombatTrig = "DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | RememberObjects$ TriggeredBlockerLKICopy | TriggerDescription$ At end of combat, the controller of the creature that blocked CARDNAME sacrifices that creature.";
final String sacBlockerEffect = "DB$ Destroy | Defined$ DelayTriggerRememberedLKI | Sacrifice$ True";
final Trigger becomesBlockedTrigger = TriggerHandler.parseTrigger(becomesBlockedTrig, getTheRing(), true);
SpellAbility endCombatExecute = AbilityFactory.getAbility(endOfCombatTrig, getTheRing());
AbilitySub sacExecute = (AbilitySub) AbilityFactory.getAbility(sacBlockerEffect, getTheRing());
endCombatExecute.setAdditionalAbility("Execute", sacExecute);
becomesBlockedTrigger.setOverridingAbility(endCombatExecute);
getTheRing().addTrigger(becomesBlockedTrigger);
} else if (level == 4) {
final String damageTrig = "Mode$ DamageDone | ValidSource$ Card.YouCtrl+IsRingbearer | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Command | TriggerDescription$ Whenever your Ring-bearer deals combat damage to a player, each opponent loses 3 life.";
final String loseEffect = "DB$ LoseLife | Defined$ Opponent | LifeAmount$ 3";
final Trigger damageTrigger = TriggerHandler.parseTrigger(damageTrig, getTheRing(), true);
SpellAbility loseExecute = AbilityFactory.getAbility(loseEffect, getTheRing());
damageTrigger.setOverridingAbility(loseExecute);
getTheRing().addTrigger(damageTrigger);
}
getTheRing().updateStateForView();
}
public void changeOwnership(Card card) {
// If lost then gained, just clear out of lost.
// If gained then lost, just clear out of gained.

View File

@@ -0,0 +1,42 @@
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 TriggerRingTemptsYou extends Trigger {
public TriggerRingTemptsYou(Map<String, String> params, Card host, boolean intrinsic) {
super(params, host, intrinsic);
}
@Override
public boolean performTest(Map<AbilityKey, Object> runParams) {
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
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.Player, AbilityKey.Card);
}
@Override
public String getImportantStackObjects(SpellAbility sa) {
StringBuilder sb = new StringBuilder();
sb.append(Localizer.getInstance().getMessage("lblPlayer")).append(": ");
sb.append(sa.getTriggeringObject(AbilityKey.Player)).append(", ");
return sb.toString();
}
}

View File

@@ -1,183 +1,184 @@
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),
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),
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);
}
}
}

View File

@@ -55,6 +55,7 @@ public enum TrackableProperty {
Token(TrackableTypes.BooleanType),
TokenCard(TrackableTypes.BooleanType),
IsCommander(TrackableTypes.BooleanType),
IsRingBearer(TrackableTypes.BooleanType),
CommanderAltType(TrackableTypes.StringType),
Damage(TrackableTypes.IntegerType),
AssignedDamage(TrackableTypes.IntegerType),
@@ -74,6 +75,7 @@ public enum TrackableProperty {
ChosenSector(TrackableTypes.StringType),
Sector(TrackableTypes.StringType),
ClassLevel(TrackableTypes.IntegerType),
RingLevel(TrackableTypes.IntegerType),
CurrentRoom(TrackableTypes.StringType),
Intensity(TrackableTypes.IntegerType),
Remembered(TrackableTypes.StringType),