mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
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:
@@ -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.
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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(" & "));
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user