mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
add new Replacement Effect its for manipulating the original request
Card#addCounter does show how it is done
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -441,6 +441,7 @@ forge-game/src/main/java/forge/game/ability/effects/RemoveFromCombatEffect.java
|
||||
forge-game/src/main/java/forge/game/ability/effects/ReorderZoneEffect.java -text
|
||||
forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java -text
|
||||
forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java -text
|
||||
forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java -text svneol=unset#text/plain
|
||||
forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java -text
|
||||
forge-game/src/main/java/forge/game/ability/effects/RevealEffect.java -text
|
||||
forge-game/src/main/java/forge/game/ability/effects/RevealHandEffect.java -text
|
||||
@@ -634,6 +635,7 @@ forge-game/src/main/java/forge/game/replacement/ReplaceGameLoss.java -text
|
||||
forge-game/src/main/java/forge/game/replacement/ReplaceMoved.java -text
|
||||
forge-game/src/main/java/forge/game/replacement/ReplaceProduceMana.java -text
|
||||
forge-game/src/main/java/forge/game/replacement/ReplaceSetInMotion.java -text
|
||||
forge-game/src/main/java/forge/game/replacement/ReplaceToken.java -text svneol=unset#text/plain
|
||||
forge-game/src/main/java/forge/game/replacement/ReplaceTurnFaceUp.java -text
|
||||
forge-game/src/main/java/forge/game/replacement/ReplaceUntap.java -text
|
||||
forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java -text
|
||||
|
||||
@@ -119,6 +119,7 @@ public enum SpellApiToAi {
|
||||
.put(ApiType.ReorderZone, AlwaysPlayAi.class)
|
||||
.put(ApiType.Repeat, RepeatAi.class)
|
||||
.put(ApiType.RepeatEach, RepeatEachAi.class)
|
||||
.put(ApiType.ReplaceEffect, AlwaysPlayAi.class)
|
||||
.put(ApiType.RestartGame, RestartGameAi.class)
|
||||
.put(ApiType.Reveal, RevealAi.class)
|
||||
.put(ApiType.RevealHand, RevealHandAi.class)
|
||||
|
||||
@@ -117,6 +117,7 @@ public enum ApiType {
|
||||
ReorderZone (ReorderZoneEffect.class),
|
||||
Repeat (RepeatEffect.class),
|
||||
RepeatEach (RepeatEachEffect.class),
|
||||
ReplaceEffect (ReplaceEffect.class),
|
||||
RestartGame (RestartGameEffect.class),
|
||||
Reveal (RevealEffect.class),
|
||||
RevealHand (RevealHandEffect.class),
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
public class ReplaceEffect extends SpellAbilityEffect {
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Card card = sa.getHostCard();
|
||||
final Game game = card.getGame();
|
||||
|
||||
final String varName = sa.getParam("VarName");
|
||||
final String varValue = sa.getParam("VarValue");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> originalParams = (Map<String, Object>) sa.getReplacingObject("OriginalParams");
|
||||
Map<String, Object> params = Maps.newHashMap(originalParams);
|
||||
|
||||
params.put(varName, AbilityUtils.calculateAmount(card, varValue, sa));
|
||||
|
||||
//try to call replacementHandler with new Params
|
||||
switch (game.getReplacementHandler().run(params)) {
|
||||
case NotReplaced:
|
||||
case Updated: {
|
||||
for (Map.Entry<String, Object> e : params.entrySet()) {
|
||||
originalParams.replace(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
private SpellAbility castSA = null;
|
||||
|
||||
private final CardDamageHistory damageHistory = new CardDamageHistory();
|
||||
private Map<Card, Map<CounterType, Integer>> countersAddedBy = new TreeMap<>();
|
||||
private Map<Card, Map<CounterType, Integer>> countersAddedBy = Maps.newTreeMap();
|
||||
private List<String> extrinsicKeyword = new ArrayList<>();
|
||||
// Hidden keywords won't be displayed on the card
|
||||
private final CopyOnWriteArrayList<String> hiddenExtrinsicKeyword = new CopyOnWriteArrayList<>();
|
||||
@@ -301,7 +301,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
// Clear old dfc trigger from the trigger handler
|
||||
getGame().getTriggerHandler().clearInstrinsicActiveTriggers(this, null);
|
||||
getGame().getTriggerHandler().registerActiveTrigger(this, false);
|
||||
HashMap<String, Object> runParams = new HashMap<>();
|
||||
Map<String, Object> runParams = Maps.newHashMap();
|
||||
runParams.put("Transformer", this);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false);
|
||||
this.incrementTransformedTimestamp();
|
||||
@@ -546,14 +546,14 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
boolean result = setState(preFaceDownState, true);
|
||||
if (result && runTriggers) {
|
||||
// Run replacement effects
|
||||
HashMap<String, Object> repParams = new HashMap<>();
|
||||
Map<String, Object> repParams = Maps.newHashMap();
|
||||
repParams.put("Event", "TurnFaceUp");
|
||||
repParams.put("Affected", this);
|
||||
getGame().getReplacementHandler().run(repParams);
|
||||
|
||||
// Run triggers
|
||||
getGame().getTriggerHandler().registerActiveTrigger(this, false);
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Card", this);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, runParams, false);
|
||||
}
|
||||
@@ -750,7 +750,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
public final void addFlipResult(final Player flipper, final String result) {
|
||||
if (flipResult == null) {
|
||||
flipResult = new TreeMap<>();
|
||||
flipResult = Maps.newTreeMap();
|
||||
}
|
||||
flipResult.put(flipper, result);
|
||||
}
|
||||
@@ -975,15 +975,24 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
if(addAmount < 0) {
|
||||
addAmount = 0; // As per rule 107.1b
|
||||
}
|
||||
final HashMap<String, Object> repParams = new HashMap<>();
|
||||
final Map<String, Object> repParams = Maps.newHashMap();
|
||||
repParams.put("Event", "AddCounter");
|
||||
repParams.put("Affected", this);
|
||||
repParams.put("CounterType", counterType);
|
||||
repParams.put("CounterNum", addAmount);
|
||||
repParams.put("EffectOnly", applyMultiplier);
|
||||
if (getGame().getReplacementHandler().run(repParams) != ReplacementResult.NotReplaced) {
|
||||
|
||||
switch (getGame().getReplacementHandler().run(repParams)) {
|
||||
case NotReplaced:
|
||||
break;
|
||||
case Updated: {
|
||||
addAmount = (int) repParams.get("CounterNum");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (canReceiveCounters(counterType)) {
|
||||
if (counterType == CounterType.DREAM && hasKeyword("CARDNAME can't have more than seven dream counters on it.")) {
|
||||
addAmount = Math.min(7 - getCounters(CounterType.DREAM), addAmount);
|
||||
@@ -1021,7 +1030,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Card", this);
|
||||
runParams.put("CounterType", counterType);
|
||||
for (int i = 0; i < addAmount; i++) {
|
||||
@@ -1042,7 +1051,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* @param counterAmount - the amount of counters added
|
||||
*/
|
||||
public final void addCountersAddedBy(final Card source, final CounterType counterType, final int counterAmount) {
|
||||
final Map<CounterType, Integer> counterMap = new TreeMap<>();
|
||||
final Map<CounterType, Integer> counterMap = Maps.newTreeMap();
|
||||
counterMap.put(counterType, counterAmount);
|
||||
countersAddedBy.put(source, counterMap);
|
||||
}
|
||||
@@ -1096,7 +1105,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
// Run triggers
|
||||
int curCounters = oldValue == null ? 0 : oldValue;
|
||||
for (int i = 0; i < delta && curCounters != 0; i++) {
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Card", this);
|
||||
runParams.put("CounterType", counterName);
|
||||
runParams.put("NewCounterAmount", --curCounters);
|
||||
@@ -2498,7 +2507,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Equip));
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Equipment", this);
|
||||
runParams.put("Card", c);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.Unequip, runParams, false);
|
||||
@@ -3044,7 +3053,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
if (tapped) { return; }
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Card", this);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams, false);
|
||||
|
||||
@@ -3065,7 +3074,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Card", this);
|
||||
getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, runParams, false);
|
||||
|
||||
@@ -3604,7 +3613,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("Card", this);
|
||||
|
||||
if (!isPhasedOut()) {
|
||||
@@ -5968,8 +5977,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
CardCollectionView preventionEffectSources = new CardCollection(shieldMap.keySet());
|
||||
Card shieldSource = preventionEffectSources.get(0);
|
||||
if (preventionEffectSources.size() > 1) {
|
||||
Map<String, Card> choiceMap = new TreeMap<>();
|
||||
List<String> choices = new ArrayList<>();
|
||||
Map<String, Card> choiceMap = Maps.newTreeMap();
|
||||
List<String> choices = Lists.newArrayList();
|
||||
for (final Card key : preventionEffectSources) {
|
||||
String effDesc = shieldMap.get(key).get("EffectString");
|
||||
int descIndex = effDesc.indexOf("SpellDescription");
|
||||
@@ -6126,7 +6135,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
@Override
|
||||
public final int replaceDamage(final int damageIn, final Card source, final boolean isCombat) {
|
||||
// Replacement effects
|
||||
final HashMap<String, Object> repParams = new HashMap<>();
|
||||
final Map<String, Object> repParams = Maps.newHashMap();
|
||||
repParams.put("Event", "DamageDone");
|
||||
repParams.put("Affected", this);
|
||||
repParams.put("DamageSource", source);
|
||||
@@ -6168,7 +6177,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = new TreeMap<>();
|
||||
final Map<String, Object> runParams = Maps.newTreeMap();
|
||||
runParams.put("DamageSource", source);
|
||||
runParams.put("DamageTarget", this);
|
||||
runParams.put("DamageAmount", damageIn);
|
||||
@@ -6958,7 +6967,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return CardFactory.getCard(pc, owner, owner == null ? null : owner.getGame());
|
||||
}
|
||||
|
||||
private static final Map<PaperCard, Card> cp2card = new HashMap<>();
|
||||
private static final Map<PaperCard, Card> cp2card = Maps.newHashMap();
|
||||
public static Card getCardForUi(IPaperCard pc) {
|
||||
if (pc instanceof PaperCard) {
|
||||
Card res = cp2card.get(pc);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package forge.game.replacement;
|
||||
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class ReplaceToken extends ReplacementEffect {
|
||||
|
||||
/**
|
||||
*
|
||||
* ReplaceProduceMana.
|
||||
* @param mapParams   HashMap<String, String>
|
||||
* @param host   Card
|
||||
*/
|
||||
public ReplaceToken(final Map<String, String> mapParams, final Card host, final boolean intrinsic) {
|
||||
super(mapParams, host, intrinsic);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public boolean canReplace(Map<String, Object> runParams) {
|
||||
if (!runParams.get("Event").equals("CreateToken") || ((int) runParams.get("TokenNum")) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("EffectOnly")) {
|
||||
final Boolean effectOnly = (Boolean) runParams.get("EffectOnly");
|
||||
if (!effectOnly) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getMapParams().containsKey("ValidPlayer")) {
|
||||
if (!matchesValid(runParams.get("Affected"), this.getMapParams().get("ValidPlayer").split(","), this.getHostCard())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) {
|
||||
sa.setReplacingObject("TokenNum", runParams.get("TokenNum"));
|
||||
sa.setReplacingObject("Player", runParams.get("Affected"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import forge.game.Game;
|
||||
import forge.game.GameLogEntryType;
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -46,7 +47,7 @@ public class ReplacementHandler {
|
||||
|
||||
//private final List<ReplacementEffect> tmpEffects = new ArrayList<ReplacementEffect>();
|
||||
|
||||
public ReplacementResult run(final HashMap<String, Object> runParams) {
|
||||
public ReplacementResult run(final Map<String, Object> runParams) {
|
||||
final Object affected = runParams.get("Affected");
|
||||
Player decider = null;
|
||||
|
||||
@@ -97,7 +98,7 @@ public class ReplacementHandler {
|
||||
* the run params,same as for triggers.
|
||||
* @return true if the event was replaced.
|
||||
*/
|
||||
public ReplacementResult run(final HashMap<String, Object> runParams, final ReplacementLayer layer, final Player decider, final Game game) {
|
||||
public ReplacementResult run(final Map<String, Object> runParams, final ReplacementLayer layer, final Player decider, final Game game) {
|
||||
final List<ReplacementEffect> possibleReplacers = new ArrayList<ReplacementEffect>();
|
||||
// Round up Non-static replacement effects ("Until EOT," or
|
||||
// "The next time you would..." etc)
|
||||
@@ -185,6 +186,8 @@ public class ReplacementHandler {
|
||||
SpellAbility tailend = effectSA;
|
||||
do {
|
||||
replacementEffect.setReplacingObjects(runParams, tailend);
|
||||
//set original Params to update them later
|
||||
tailend.setReplacingObject("OriginalParams", runParams);
|
||||
tailend = tailend.getSubAbility();
|
||||
} while(tailend != null);
|
||||
|
||||
@@ -194,6 +197,8 @@ public class ReplacementHandler {
|
||||
SpellAbility tailend = effectSA;
|
||||
do {
|
||||
replacementEffect.setReplacingObjects(runParams, tailend);
|
||||
//set original Params to update them later
|
||||
tailend.setReplacingObject("OriginalParams", runParams);
|
||||
tailend = tailend.getSubAbility();
|
||||
} while(tailend != null);
|
||||
}
|
||||
@@ -250,6 +255,10 @@ public class ReplacementHandler {
|
||||
manaAb.getManaPart().produceMana(rep, player1, manaAb);
|
||||
} else {
|
||||
player.getController().playSpellAbilityNoStack(effectSA, true);
|
||||
// if the spellability is a replace effect then its some new logic
|
||||
if (ApiType.ReplaceEffect.equals(effectSA.getApi())) {
|
||||
return ReplacementResult.Updated;
|
||||
}
|
||||
}
|
||||
|
||||
return ReplacementResult.Replaced;
|
||||
|
||||
@@ -7,5 +7,6 @@ package forge.game.replacement;
|
||||
public enum ReplacementResult {
|
||||
Replaced,
|
||||
NotReplaced,
|
||||
Prevented;
|
||||
Prevented,
|
||||
Updated;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ import java.util.Map;
|
||||
*
|
||||
*/
|
||||
public enum ReplacementType {
|
||||
AddCounter(ReplaceAddCounter.class),
|
||||
AddCounter(ReplaceAddCounter.class),
|
||||
Counter(ReplaceCounter.class),
|
||||
CreateToken(ReplaceToken.class),
|
||||
DamageDone(ReplaceDamage.class),
|
||||
Destroy(ReplaceDestroy.class),
|
||||
Discard(ReplaceDiscard.class),
|
||||
@@ -24,12 +25,12 @@ public enum ReplacementType {
|
||||
SetInMotion(ReplaceSetInMotion.class),
|
||||
TurnFaceUp(ReplaceTurnFaceUp.class),
|
||||
Untap(ReplaceUntap.class);
|
||||
|
||||
|
||||
Class<? extends ReplacementEffect> clasz;
|
||||
private ReplacementType(Class<? extends ReplacementEffect> cls) {
|
||||
clasz = cls;
|
||||
}
|
||||
|
||||
|
||||
public static ReplacementType getTypeFor(ReplacementEffect e) {
|
||||
final Class<? extends ReplacementEffect> cls = e.getClass();
|
||||
for (final ReplacementType v : ReplacementType.values()) {
|
||||
|
||||
Reference in New Issue
Block a user