Merge remote-tracking branch 'upstream/master'

This commit is contained in:
CCTV-1
2019-09-15 08:24:46 +08:00
24 changed files with 241 additions and 188 deletions

View File

@@ -1601,8 +1601,8 @@ public class ComputerUtilCard {
} }
pumped.addNewPT(c.getCurrentPower(), c.getCurrentToughness(), timestamp); pumped.addNewPT(c.getCurrentPower(), c.getCurrentToughness(), timestamp);
pumped.setPTBoost(c.getPTBoostMap()); pumped.setPTBoost(c.getPTBoostTable());
pumped.addPTBoost(power + berserkPower, toughness, timestamp); pumped.addPTBoost(power + berserkPower, toughness, timestamp, null);
pumped.addChangedCardKeywords(kws, null, false, false, timestamp); pumped.addChangedCardKeywords(kws, null, false, false, timestamp);
Set<CounterType> types = c.getCounters().keySet(); Set<CounterType> types = c.getCounters().keySet();
for(CounterType ct : types) { for(CounterType ct : types) {
@@ -1649,8 +1649,8 @@ public class ComputerUtilCard {
list.add(vCard); // account for the static abilities that may be present on the card itself list.add(vCard); // account for the static abilities that may be present on the card itself
for (final Card c : list) { for (final Card c : list) {
// remove old boost that might be copied // remove old boost that might be copied
vCard.removePTBoost(c.getTimestamp());
for (final StaticAbility stAb : c.getStaticAbilities()) { for (final StaticAbility stAb : c.getStaticAbilities()) {
vCard.removePTBoost(c.getTimestamp(), stAb.getId());
final Map<String, String> params = stAb.getMapParams(); final Map<String, String> params = stAb.getMapParams();
if (!params.get("Mode").equals("Continuous")) { if (!params.get("Mode").equals("Continuous")) {
continue; continue;
@@ -1683,7 +1683,7 @@ public class ComputerUtilCard {
def = AbilityUtils.calculateAmount(c, addT, stAb); def = AbilityUtils.calculateAmount(c, addT, stAb);
} }
} }
vCard.addPTBoost(att, def, c.getTimestamp()); vCard.addPTBoost(att, def, c.getTimestamp(), stAb.getId());
} }
} }
} }

View File

@@ -246,7 +246,7 @@ public class GameCopier {
newCard.addType(type); newCard.addType(type);
} }
for (StaticAbility stAb : c.getStaticAbilities()) { for (StaticAbility stAb : c.getStaticAbilities()) {
newCard.addStaticAbility(stAb); newCard.addStaticAbility(stAb.copy(newCard, true));
} }
for (SpellAbility sa : c.getSpellAbilities()) { for (SpellAbility sa : c.getSpellAbilities()) {
SpellAbility saCopy = sa.copy(newCard, true); SpellAbility saCopy = sa.copy(newCard, true);
@@ -277,7 +277,7 @@ public class GameCopier {
// TODO: Copy the full list with timestamps. // TODO: Copy the full list with timestamps.
newCard.addNewPT(setPower, setToughness, newGame.getNextTimestamp()); newCard.addNewPT(setPower, setToughness, newGame.getNextTimestamp());
} }
newCard.setPTBoost(c.getPTBoostMap()); newCard.setPTBoost(c.getPTBoostTable());
newCard.setDamage(c.getDamage()); newCard.setDamage(c.getDamage());
newCard.setChangedCardTypes(c.getChangedCardTypesMap()); newCard.setChangedCardTypes(c.getChangedCardTypesMap());

View File

@@ -798,7 +798,7 @@ public class StaticEffect {
} }
// remove P/T bonus // remove P/T bonus
affectedCard.removePTBoost(getTimestamp()); affectedCard.removePTBoost(getTimestamp(), ability.getId());
// the view is updated in GameAction#checkStaticAbilities to avoid flickering // the view is updated in GameAction#checkStaticAbilities to avoid flickering

View File

@@ -9,6 +9,11 @@ import java.util.Map;
public enum AbilityKey { public enum AbilityKey {
AbilityMana("AbilityMana"), AbilityMana("AbilityMana"),
Affected("Affected"), Affected("Affected"),
Attach("Attach"),
AllVotes("AllVotes"),
AttachSource("AttachSource"),
AttachTarget("AttachTarget"),
Attacked("Attacked"),
Attacker("Attacker"), Attacker("Attacker"),
Attackers("Attackers"), Attackers("Attackers"),
AttackingPlayer("AttackingPlayer"), AttackingPlayer("AttackingPlayer"),
@@ -16,35 +21,51 @@ public enum AbilityKey {
Blocker("Blocker"), Blocker("Blocker"),
Blockers("Blockers"), Blockers("Blockers"),
Card("Card"), Card("Card"),
Cards("Cards"),
CardLKI("CardLKI"), CardLKI("CardLKI"),
Cause("Cause"), Cause("Cause"),
Causer("Causer"), Causer("Causer"),
Championed("Championed"), Championed("Championed"),
CounterAmount("CounterAmount"),
CounteredSA("CounteredSA"), CounteredSA("CounteredSA"),
CounterType("CounterType"),
CumulativeUpkeepPaid("CumulativeUpkeepPaid"),
DamageAmount("DamageAmount"), DamageAmount("DamageAmount"),
DamageSource("DamageSource"), DamageSource("DamageSource"),
DamageSources("DamageSources"),
DamageTarget("DamageTarget"), DamageTarget("DamageTarget"),
DamageTargets("DamageTargets"),
Defender("Defender"), Defender("Defender"),
Defenders("Defenders"),
DefendingPlayer("DefendingPlayer"), DefendingPlayer("DefendingPlayer"),
Destination("Destination"), Destination("Destination"),
Devoured("Devoured"),
EchoPaid("EchoPaid"),
Exploited("Exploited"),
Event("Event"), Event("Event"),
Fighter("Fighter"), Fighter("Fighter"),
Fizzle("Fizzle"), Fizzle("Fizzle"),
IsCombatDamage("IsCombatDamage"), IsCombatDamage("IsCombatDamage"),
PayingMana("PayingMana"),
Player("Player"), Player("Player"),
IndividualCostPaymentInstance("IndividualCostPaymentInstance"), IndividualCostPaymentInstance("IndividualCostPaymentInstance"),
MonstrosityAmount("MonstrosityAmount"), MonstrosityAmount("MonstrosityAmount"),
NewCounterAmount("NewCounterAmount"),
NumBlockers("NumBlockers"), NumBlockers("NumBlockers"),
Object("Object"),
Objects("Objects"), Objects("Objects"),
OtherAttackers("OtherAttackers"),
Origin("Origin"), Origin("Origin"),
OriginalController("OriginalController"), OriginalController("OriginalController"),
Produced("Produced"), Produced("Produced"),
Result("Result"), Result("Result"),
Scheme("Scheme"), Scheme("Scheme"),
Source("Source"),
SpellAbilityStackInstance("SpellAbilityStackInstance"), SpellAbilityStackInstance("SpellAbilityStackInstance"),
StackSa("StackSa"), StackSa("StackSa"),
StackSi("StackSi"), StackSi("StackSi"),
Target("Target"), Target("Target"),
Transformer("Transformer"),
Won("Won"); Won("Won");

View File

@@ -52,7 +52,7 @@ public class PumpAllEffect extends SpellAbilityEffect {
boolean redrawPT = false; boolean redrawPT = false;
if (a != 0 || d != 0) { if (a != 0 || d != 0) {
tgtC.addPTBoost(a, d, timestamp); tgtC.addPTBoost(a, d, timestamp, 0);
redrawPT = true; redrawPT = true;
} }
@@ -76,7 +76,7 @@ public class PumpAllEffect extends SpellAbilityEffect {
@Override @Override
public void run() { public void run() {
tgtC.removePTBoost(timestamp); tgtC.removePTBoost(timestamp, 0);
tgtC.removeChangedCardKeywords(timestamp); tgtC.removeChangedCardKeywords(timestamp);
for (String kw : hiddenkws) { for (String kw : hiddenkws) {

View File

@@ -56,7 +56,7 @@ public class PumpEffect extends SpellAbilityEffect {
} }
if (a != 0 || d != 0) { if (a != 0 || d != 0) {
gameCard.addPTBoost(a, d, timestamp); gameCard.addPTBoost(a, d, timestamp, 0);
redrawPT = true; redrawPT = true;
} }
@@ -84,7 +84,7 @@ public class PumpEffect extends SpellAbilityEffect {
@Override @Override
public void run() { public void run() {
gameCard.removePTBoost(timestamp); gameCard.removePTBoost(timestamp, 0);
boolean updateText = false; boolean updateText = false;
updateText = gameCard.removeCanBlockAny(timestamp) || updateText; updateText = gameCard.removeCanBlockAny(timestamp) || updateText;
updateText = gameCard.removeCanBlockAdditional(timestamp) || updateText; updateText = gameCard.removeCanBlockAdditional(timestamp) || updateText;

View File

@@ -1,6 +1,7 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.event.GameEventCardRegenerated; import forge.game.event.GameEventCardRegenerated;
@@ -9,8 +10,6 @@ import forge.game.trigger.TriggerType;
import java.util.Map; import java.util.Map;
import com.google.common.collect.Maps;
public class RegenerationEffect extends SpellAbilityEffect { public class RegenerationEffect extends SpellAbilityEffect {
/* /*
@@ -44,10 +43,9 @@ public class RegenerationEffect extends SpellAbilityEffect {
} }
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(c);
runParams.put("Card", c); runParams.put(AbilityKey.Cause, host);
runParams.put("Cause", host); game.getTriggerHandler().runTrigger(TriggerType.Regenerated, runParams, false);
game.getTriggerHandler().runTriggerOld(TriggerType.Regenerated, runParams, false);
} }
} }

View File

@@ -1,6 +1,7 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
@@ -14,9 +15,7 @@ import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
import java.util.List; import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public class RevealEffect extends SpellAbilityEffect { public class RevealEffect extends SpellAbilityEffect {
@@ -74,14 +73,7 @@ public class RevealEffect extends SpellAbilityEffect {
game.getAction().reveal(revealed, p); game.getAction().reveal(revealed, p);
for (final Card c : revealed) { for (final Card c : revealed) {
Map<String, Object> runParams = Maps.newHashMap(); game.getTriggerHandler().runTrigger(TriggerType.Revealed, AbilityKey.mapFromCard(c), false);
runParams.put("Card", c);
/*
if (sa.hasParam("MiracleCost")) {
runParams.put("Miracle", true);
}
//*/
game.getTriggerHandler().runTriggerOld(TriggerType.Revealed, runParams, false);
if (sa.hasParam("RememberRevealed")) { if (sa.hasParam("RememberRevealed")) {
host.addRemembered(c); host.addRemembered(c);
} }

View File

@@ -1,10 +1,10 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import com.google.common.collect.Maps;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.Game; import forge.game.Game;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.GameEntityCounterTable; import forge.game.GameEntityCounterTable;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.*; import forge.game.card.*;
@@ -36,10 +36,9 @@ public class SacrificeEffect extends SpellAbilityEffect {
isPaid = activator.getController().payManaOptional(card, new Cost(sa.getParam("Echo"), true), isPaid = activator.getController().payManaOptional(card, new Cost(sa.getParam("Echo"), true),
sa, "Pay Echo", ManaPaymentPurpose.Echo); sa, "Pay Echo", ManaPaymentPurpose.Echo);
} }
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(card);
runParams.put("EchoPaid", Boolean.valueOf(isPaid)); runParams.put(AbilityKey.EchoPaid, isPaid);
runParams.put("Card", card); game.getTriggerHandler().runTrigger(TriggerType.PayEcho, runParams, false);
game.getTriggerHandler().runTriggerOld(TriggerType.PayEcho, runParams, false);
if (isPaid || !card.getController().equals(activator)) { if (isPaid || !card.getController().equals(activator)) {
return; return;
} }
@@ -65,11 +64,10 @@ public class SacrificeEffect extends SpellAbilityEffect {
sb.append("Cumulative upkeep for ").append(card); sb.append("Cumulative upkeep for ").append(card);
boolean isPaid = activator.getController().payManaOptional(card, payCost, sa, sb.toString(), ManaPaymentPurpose.CumulativeUpkeep); boolean isPaid = activator.getController().payManaOptional(card, payCost, sa, sb.toString(), ManaPaymentPurpose.CumulativeUpkeep);
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(card);
runParams.put("CumulativeUpkeepPaid", Boolean.valueOf(isPaid)); runParams.put(AbilityKey.CumulativeUpkeepPaid, isPaid);
runParams.put("Card", card); runParams.put(AbilityKey.PayingMana, StringUtils.join(sa.getPayingMana(), ""));
runParams.put("PayingMana", StringUtils.join(sa.getPayingMana(), "")); game.getTriggerHandler().runTrigger(TriggerType.PayCumulativeUpkeep, runParams, false);
game.getTriggerHandler().runTriggerOld(TriggerType.PayCumulativeUpkeep, runParams, false);
if (isPaid || !card.getController().equals(activator)) { if (isPaid || !card.getController().equals(activator)) {
return; return;
} }
@@ -147,16 +145,15 @@ public class SacrificeEffect extends SpellAbilityEffect {
// Run Devour Trigger // Run Devour Trigger
if (devour) { if (devour) {
card.addDevoured(lKICopy); card.addDevoured(lKICopy);
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Devoured", sac); runParams.put(AbilityKey.Devoured, sac);
game.getTriggerHandler().runTriggerOld(TriggerType.Devoured, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.Devoured, runParams, false);
} }
if (exploit) { if (exploit) {
card.addExploited(lKICopy); card.addExploited(lKICopy);
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(card);
runParams.put("Exploited", lKICopy); runParams.put(AbilityKey.Exploited, lKICopy);
runParams.put("Card", card); game.getTriggerHandler().runTrigger(TriggerType.Exploited, runParams, false);
game.getTriggerHandler().runTriggerOld(TriggerType.Exploited, runParams, false);
} }
if (wasDestroyed || wasSacrificed) { if (wasDestroyed || wasSacrificed) {
countSacrificed++; countSacrificed++;

View File

@@ -1,8 +1,8 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import com.google.common.collect.Maps;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
@@ -46,9 +46,9 @@ public class SetInMotionEffect extends SpellAbilityEffect {
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Scheme", controller.getActiveScheme()); runParams.put(AbilityKey.Scheme, controller.getActiveScheme());
game.getTriggerHandler().runTriggerOld(TriggerType.SetInMotion, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.SetInMotion, runParams, false);
} else { } else {
controller.setSchemeInMotion(); controller.setSchemeInMotion();
} }

View File

@@ -5,13 +5,13 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import forge.game.ability.AbilityKey;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
@@ -98,10 +98,10 @@ public class VoteEffect extends SpellAbilityEffect {
host.getGame().getAction().nofityOfValue(sa, p, result + "\r\nCurrent Votes:" + votes, p); host.getGame().getAction().nofityOfValue(sa, p, result + "\r\nCurrent Votes:" + votes, p);
} }
} }
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("AllVotes", votes); runParams.put(AbilityKey.AllVotes, votes);
game.getTriggerHandler().runTriggerOld(TriggerType.Vote, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.Vote, runParams, false);
List<String> subAbs = Lists.newArrayList(); List<String> subAbs = Lists.newArrayList();
final List<Object> mostVotes = getMostVotes(votes); final List<Object> mostVotes = getMostVotes(votes);

View File

@@ -30,6 +30,7 @@ import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser; import forge.card.mana.ManaCostParser;
import forge.game.*; import forge.game.*;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.ability.effects.CharmEffect; import forge.game.ability.effects.CharmEffect;
@@ -197,7 +198,9 @@ public class Card extends GameEntity implements Comparable<Card> {
// stack of set power/toughness // stack of set power/toughness
private Map<Long, Pair<Integer,Integer>> newPT = Maps.newTreeMap(); private Map<Long, Pair<Integer,Integer>> newPT = Maps.newTreeMap();
private Map<Long, Pair<Integer,Integer>> newPTCharacterDefining = Maps.newTreeMap(); private Map<Long, Pair<Integer,Integer>> newPTCharacterDefining = Maps.newTreeMap();
private Map<Long, Pair<Integer,Integer>> boostPT = Maps.newTreeMap();
// x=Static Avility id or 0, y=timestamp
private Table<Integer, Long, Pair<Integer,Integer>> boostPT = TreeBasedTable.create();
private String basePowerString = null; private String basePowerString = null;
private String baseToughnessString = null; private String baseToughnessString = null;
@@ -567,9 +570,9 @@ public class Card extends GameEntity implements Comparable<Card> {
// Clear old dfc trigger from the trigger handler // Clear old dfc trigger from the trigger handler
getGame().getTriggerHandler().clearInstrinsicActiveTriggers(this, null); getGame().getTriggerHandler().clearInstrinsicActiveTriggers(this, null);
getGame().getTriggerHandler().registerActiveTrigger(this, false); getGame().getTriggerHandler().registerActiveTrigger(this, false);
Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Transformer", this); runParams.put(AbilityKey.Transformer, this);
getGame().getTriggerHandler().runTriggerOld(TriggerType.Transformed, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false);
incrementTransformedTimestamp(); incrementTransformedTimestamp();
return result; return result;
@@ -687,9 +690,7 @@ public class Card extends GameEntity implements Comparable<Card> {
// Run triggers // Run triggers
getGame().getTriggerHandler().registerActiveTrigger(this, false); getGame().getTriggerHandler().registerActiveTrigger(this, false);
final Map<String, Object> runParams = Maps.newTreeMap(); getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, AbilityKey.mapFromCard(this), false);
runParams.put("Card", this);
getGame().getTriggerHandler().runTriggerOld(TriggerType.TurnFaceUp, runParams, false);
} }
return result; return result;
} }
@@ -1281,18 +1282,17 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put("Card", this); runParams.put(AbilityKey.Source, source);
runParams.put("Source", source); runParams.put(AbilityKey.CounterType, counterType);
runParams.put("CounterType", counterType);
for (int i = 0; i < addAmount; i++) { for (int i = 0; i < addAmount; i++) {
runParams.put("CounterAmount", oldValue + i + 1); runParams.put(AbilityKey.CounterAmount, oldValue + i + 1);
getGame().getTriggerHandler().runTriggerOld( getGame().getTriggerHandler().runTrigger(
TriggerType.CounterAdded, Maps.newHashMap(runParams), false); TriggerType.CounterAdded, Maps.newHashMap(runParams), false);
} }
if (addAmount > 0) { if (addAmount > 0) {
runParams.put("CounterAmount", addAmount); runParams.put(AbilityKey.CounterAmount, addAmount);
getGame().getTriggerHandler().runTriggerOld( getGame().getTriggerHandler().runTrigger(
TriggerType.CounterAddedOnce, Maps.newHashMap(runParams), false); TriggerType.CounterAddedOnce, Maps.newHashMap(runParams), false);
} }
} else { } else {
@@ -1340,10 +1340,10 @@ public class Card extends GameEntity implements Comparable<Card> {
@Override @Override
public final void subtractCounter(final CounterType counterName, final int n) { public final void subtractCounter(final CounterType counterName, final int n) {
Integer oldValue = getCounters(counterName); int oldValue = getCounters(counterName);
int newValue = oldValue == null ? 0 : Math.max(oldValue - n, 0); int newValue = Math.max(oldValue - n, 0);
final int delta = (oldValue == null ? 0 : oldValue) - newValue; final int delta = oldValue - newValue;
if (delta == 0) { return; } if (delta == 0) { return; }
int powerBonusBefore = getPowerBonusFromCounters(); int powerBonusBefore = getPowerBonusFromCounters();
@@ -1359,19 +1359,18 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
// Play the Subtract Counter sound // Play the Subtract Counter sound
getGame().fireEvent(new GameEventCardCounters(this, counterName, oldValue == null ? 0 : oldValue, newValue)); getGame().fireEvent(new GameEventCardCounters(this, counterName, oldValue, newValue));
// Run triggers // Run triggers
int curCounters = oldValue == null ? 0 : oldValue; int curCounters = oldValue;
final Map<String, Object> runParams = Maps.newTreeMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put("Card", this); runParams.put(AbilityKey.CounterType, counterName);
runParams.put("CounterType", counterName);
for (int i = 0; i < delta && curCounters != 0; i++) { for (int i = 0; i < delta && curCounters != 0; i++) {
runParams.put("NewCounterAmount", --curCounters); runParams.put(AbilityKey.NewCounterAmount, --curCounters);
getGame().getTriggerHandler().runTriggerOld(TriggerType.CounterRemoved, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams, false);
} }
runParams.put("CounterAmount", delta); runParams.put(AbilityKey.CounterAmount, delta);
getGame().getTriggerHandler().runTriggerOld(TriggerType.CounterRemovedOnce, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemovedOnce, runParams, false);
} }
@Override @Override
@@ -2935,10 +2934,10 @@ public class Card extends GameEntity implements Comparable<Card> {
getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, entity)); getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, entity));
// run trigger // run trigger
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("AttachSource", this); runParams.put(AbilityKey.AttachSource, this);
runParams.put("AttachTarget", entity); runParams.put(AbilityKey.AttachTarget, entity);
getController().getGame().getTriggerHandler().runTriggerOld(TriggerType.Attached, runParams, false); getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false);
} }
@@ -2957,10 +2956,10 @@ public class Card extends GameEntity implements Comparable<Card> {
getGame().fireEvent(new GameEventCardAttachment(this, entity, null)); getGame().fireEvent(new GameEventCardAttachment(this, entity, null));
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newTreeMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Attach", this); runParams.put(AbilityKey.Attach, this);
runParams.put("Object", entity); runParams.put(AbilityKey.Object, entity);
getGame().getTriggerHandler().runTriggerOld(TriggerType.Unattach, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.Unattach, runParams, false);
runUnattachCommands(); runUnattachCommands();
} }
@@ -3477,23 +3476,21 @@ public class Card extends GameEntity implements Comparable<Card> {
return result; return result;
} }
public void addPTBoost(final Integer power, final Integer toughness, final long timestamp) { public void addPTBoost(final Integer power, final Integer toughness, final long timestamp, final Integer staticId) {
boostPT.put(timestamp, Pair.of(power, toughness)); boostPT.put(staticId == null ? 0 : staticId, timestamp, Pair.of(power, toughness));
} }
public void removePTBoost(final long timestamp) { public void removePTBoost(final long timestamp, final Integer staticId) {
boostPT.remove(timestamp); boostPT.remove(staticId, timestamp);
} }
public Map<Long, Pair<Integer, Integer>> getPTBoostMap() { public Table<Integer, Long, Pair<Integer, Integer>> getPTBoostTable() {
return ImmutableMap.copyOf(boostPT); return ImmutableTable.copyOf(boostPT);
} }
public void setPTBoost(Map<Long, Pair<Integer, Integer>> map) { public void setPTBoost(Table<Integer, Long, Pair<Integer, Integer>> table) {
this.boostPT.clear(); this.boostPT.clear();
for (Map.Entry<Long, Pair<Integer,Integer>> e : map.entrySet()) { boostPT.putAll(table);
this.boostPT.put(e.getKey(), Pair.of(e.getValue().getLeft(), e.getValue().getRight()));
}
} }
public final boolean isUntapped() { public final boolean isUntapped() {
@@ -3516,10 +3513,9 @@ public class Card extends GameEntity implements Comparable<Card> {
if (tapped) { return; } if (tapped) { return; }
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newTreeMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put("Card", this); runParams.put(AbilityKey.Attacker, attacker);
runParams.put("Attacker", attacker); getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams, false);
getGame().getTriggerHandler().runTriggerOld(TriggerType.Taps, runParams, false);
setTapped(true); setTapped(true);
getGame().fireEvent(new GameEventCardTapped(this, true)); getGame().fireEvent(new GameEventCardTapped(this, true));
@@ -3538,9 +3534,7 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newTreeMap(); getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, AbilityKey.mapFromCard(this), false);
runParams.put("Card", this);
getGame().getTriggerHandler().runTriggerOld(TriggerType.Untaps, runParams, false);
for (final GameCommand var : untapCommandList) { for (final GameCommand var : untapCommandList) {
var.run(); var.run();
@@ -3971,12 +3965,8 @@ public class Card extends GameEntity implements Comparable<Card> {
return null; return null;
} }
public final StaticAbility addStaticAbility(final StaticAbility stAb) { public final StaticAbility addStaticAbility(final StaticAbility stAb) {
return addStaticAbility(stAb, false); currentState.addStaticAbility(stAb);
} return stAb;
public final StaticAbility addStaticAbility(final StaticAbility stAb, boolean intrinsic) {
final StaticAbility stAbCopy = new StaticAbility(stAb, this);
currentState.addStaticAbility(stAbCopy);
return stAbCopy;
} }
public final void removeStaticAbility(StaticAbility stAb) { public final void removeStaticAbility(StaticAbility stAb) {
currentState.removeStaticAbility(stAb); currentState.removeStaticAbility(stAb);
@@ -4099,13 +4089,12 @@ public class Card extends GameEntity implements Comparable<Card> {
return false; return false;
} }
final Map<String, Object> runParams = Maps.newTreeMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put("Card", this);
if (!isPhasedOut()) { if (!isPhasedOut()) {
// If this is currently PhasedIn, it's about to phase out. // If this is currently PhasedIn, it's about to phase out.
// Run trigger before it does because triggers don't work with phased out objects // Run trigger before it does because triggers don't work with phased out objects
getGame().getTriggerHandler().runTriggerOld(TriggerType.PhaseOut, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false);
} }
setPhasedOut(!phasedOut); setPhasedOut(!phasedOut);
@@ -4117,7 +4106,7 @@ public class Card extends GameEntity implements Comparable<Card> {
if (!phasedOut) { if (!phasedOut) {
// Just phased in, time to run the phased in trigger // Just phased in, time to run the phased in trigger
getGame().getTriggerHandler().registerActiveTrigger(this, false); getGame().getTriggerHandler().registerActiveTrigger(this, false);
getGame().getTriggerHandler().runTriggerOld(TriggerType.PhaseIn, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.PhaseIn, runParams, false);
} }
return true; return true;
@@ -4900,17 +4889,17 @@ public class Card extends GameEntity implements Comparable<Card> {
source.addDealtDamageToThisTurn(this, damageIn); source.addDealtDamageToThisTurn(this, damageIn);
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newTreeMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("DamageSource", source); runParams.put(AbilityKey.DamageSource, source);
runParams.put("DamageTarget", this); runParams.put(AbilityKey.DamageTarget, this);
runParams.put("DamageAmount", damageIn); runParams.put(AbilityKey.DamageAmount, damageIn);
runParams.put("IsCombatDamage", isCombat); runParams.put(AbilityKey.IsCombatDamage, isCombat);
if (!isCombat) { if (!isCombat) {
runParams.put("SpellAbilityStackInstance", game.stack.peek()); runParams.put(AbilityKey.SpellAbilityStackInstance, game.stack.peek());
} }
// Defending player at the time the damage was dealt // Defending player at the time the damage was dealt
runParams.put("DefendingPlayer", game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null); runParams.put(AbilityKey.DefendingPlayer, game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null);
getGame().getTriggerHandler().runTriggerOld(TriggerType.DamageDone, runParams, false); getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false);
GameEventCardDamaged.DamageType damageType = DamageType.Normal; GameEventCardDamaged.DamageType damageType = DamageType.Normal;
if (isPlaneswalker()) { if (isPlaneswalker()) {
@@ -5008,10 +4997,9 @@ public class Card extends GameEntity implements Comparable<Card> {
exertedByPlayer.add(getController()); exertedByPlayer.add(getController());
exertThisTurn++; exertThisTurn++;
view.updateExertedThisTurn(this, true); view.updateExertedThisTurn(this, true);
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put("Card", this); runParams.put(AbilityKey.Player, getController());
runParams.put("Player", getController()); game.getTriggerHandler().runTrigger(TriggerType.Exerted, runParams, false);
game.getTriggerHandler().runTriggerOld(TriggerType.Exerted, runParams, false);
} }
public boolean isExertedBy(final Player player) { public boolean isExertedBy(final Player player) {

View File

@@ -7,11 +7,11 @@ import java.util.Map;
import com.google.common.collect.ForwardingTable; import com.google.common.collect.ForwardingTable;
import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.collect.Table; import com.google.common.collect.Table;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.ability.AbilityKey;
import forge.game.keyword.Keyword; import forge.game.keyword.Keyword;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType; import forge.game.trigger.TriggerType;
@@ -34,12 +34,12 @@ public class CardDamageMap extends ForwardingTable<Card, GameEntity, Integer> {
} }
if (sum > 0) { if (sum > 0) {
final GameEntity ge = e.getKey(); final GameEntity ge = e.getKey();
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("DamageTarget", ge); runParams.put(AbilityKey.DamageTarget, ge);
runParams.put("DamageAmount", sum); runParams.put(AbilityKey.DamageAmount, sum);
runParams.put("IsCombatDamage", isCombat); runParams.put(AbilityKey.IsCombatDamage, isCombat);
ge.getGame().getTriggerHandler().runTriggerOld(TriggerType.DamagePreventedOnce, runParams, false); ge.getGame().getTriggerHandler().runTrigger(TriggerType.DamagePreventedOnce, runParams, false);
} }
} }
} }
@@ -53,13 +53,13 @@ public class CardDamageMap extends ForwardingTable<Card, GameEntity, Integer> {
sum += i; sum += i;
} }
if (sum > 0) { if (sum > 0) {
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("DamageSource", sourceLKI); runParams.put(AbilityKey.DamageSource, sourceLKI);
runParams.put("DamageTargets", Sets.newHashSet(e.getValue().keySet())); runParams.put(AbilityKey.DamageTargets, Sets.newHashSet(e.getValue().keySet()));
runParams.put("DamageAmount", sum); runParams.put(AbilityKey.DamageAmount, sum);
runParams.put("IsCombatDamage", isCombat); runParams.put(AbilityKey.IsCombatDamage, isCombat);
sourceLKI.getGame().getTriggerHandler().runTriggerOld(TriggerType.DamageDealtOnce, runParams, false); sourceLKI.getGame().getTriggerHandler().runTrigger(TriggerType.DamageDealtOnce, runParams, false);
if (sourceLKI.hasKeyword(Keyword.LIFELINK)) { if (sourceLKI.hasKeyword(Keyword.LIFELINK)) {
sourceLKI.getController().gainLife(sum, sourceLKI, sa); sourceLKI.getController().gainLife(sum, sourceLKI, sa);
@@ -74,13 +74,13 @@ public class CardDamageMap extends ForwardingTable<Card, GameEntity, Integer> {
} }
if (sum > 0) { if (sum > 0) {
final GameEntity ge = e.getKey(); final GameEntity ge = e.getKey();
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("DamageTarget", ge); runParams.put(AbilityKey.DamageTarget, ge);
runParams.put("DamageSources", Sets.newHashSet(e.getValue().keySet())); runParams.put(AbilityKey.DamageSources, Sets.newHashSet(e.getValue().keySet()));
runParams.put("DamageAmount", sum); runParams.put(AbilityKey.DamageAmount, sum);
runParams.put("IsCombatDamage", isCombat); runParams.put(AbilityKey.IsCombatDamage, isCombat);
ge.getGame().getTriggerHandler().runTriggerOld(TriggerType.DamageDoneOnce, runParams, false); ge.getGame().getTriggerHandler().runTrigger(TriggerType.DamageDoneOnce, runParams, false);
} }
} }
} }

View File

@@ -529,7 +529,7 @@ public class CardState extends GameObject {
staticAbilities.clear(); staticAbilities.clear();
for (StaticAbility sa : source.staticAbilities) { for (StaticAbility sa : source.staticAbilities) {
if (sa.isIntrinsic()) { if (sa.isIntrinsic()) {
staticAbilities.add(new StaticAbility(sa, this.card)); staticAbilities.add(sa.copy(card, lki));
} }
} }
} }

View File

@@ -7,10 +7,10 @@ import java.util.Map;
import com.google.common.collect.ForwardingTable; import com.google.common.collect.ForwardingTable;
import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table; import com.google.common.collect.Table;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType; import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -54,9 +54,9 @@ public class CardZoneTable extends ForwardingTable<ZoneType, ZoneType, CardColle
public void triggerChangesZoneAll(final Game game) { public void triggerChangesZoneAll(final Game game) {
if (!isEmpty()) { if (!isEmpty()) {
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Cards", new CardZoneTable(this)); runParams.put(AbilityKey.Cards, new CardZoneTable(this));
game.getTriggerHandler().runTriggerOld(TriggerType.ChangesZoneAll, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, runParams, false);
} }
} }

View File

@@ -24,6 +24,7 @@ import forge.game.GameEntity;
import forge.game.GameEntityCounterTable; import forge.game.GameEntityCounterTable;
import forge.game.GameLogEntryType; import forge.game.GameLogEntryType;
import forge.game.GameObjectMap; import forge.game.GameObjectMap;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
@@ -632,11 +633,11 @@ public class Combat {
defenders.add(getDefenderByAttacker(ab)); defenders.add(getDefenderByAttacker(ab));
for (Card attacker : ab.getAttackers()) { for (Card attacker : ab.getAttackers()) {
// Run Unblocked Trigger // Run Unblocked Trigger
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Attacker", attacker); runParams.put(AbilityKey.Attacker, attacker);
runParams.put("Defender",getDefenderByAttacker(attacker)); runParams.put(AbilityKey.Defender,getDefenderByAttacker(attacker));
runParams.put("DefendingPlayer", getDefenderPlayerByAttacker(attacker)); runParams.put(AbilityKey.DefendingPlayer, getDefenderPlayerByAttacker(attacker));
game.getTriggerHandler().runTriggerOld(TriggerType.AttackerUnblocked, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false);
} }
} }
} }
@@ -644,10 +645,10 @@ public class Combat {
// triggers for Coveted Jewel // triggers for Coveted Jewel
// currently there is only one attacking player // currently there is only one attacking player
// should be updated when two-headed-giant is done // should be updated when two-headed-giant is done
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("AttackingPlayer", getAttackingPlayer()); runParams.put(AbilityKey.AttackingPlayer, getAttackingPlayer());
runParams.put("Defenders", defenders); runParams.put(AbilityKey.Defenders, defenders);
game.getTriggerHandler().runTriggerOld(TriggerType.AttackerUnblockedOnce, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.AttackerUnblockedOnce, runParams, false);
} }
} }

View File

@@ -20,13 +20,13 @@ package forge.game.combat;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import forge.card.CardType; import forge.card.CardType;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GlobalRuleChange; import forge.game.GlobalRuleChange;
import forge.game.ability.AbilityKey;
import forge.game.card.*; import forge.game.card.*;
import forge.game.cost.Cost; import forge.game.cost.Cost;
import forge.game.keyword.Keyword; import forge.game.keyword.Keyword;
@@ -305,15 +305,15 @@ public class CombatUtil {
*/ */
public static void checkDeclaredAttacker(final Game game, final Card c, final Combat combat) { public static void checkDeclaredAttacker(final Game game, final Card c, final Combat combat) {
// Run triggers // Run triggers
final Map<String, Object> runParams = Maps.newHashMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put("Attacker", c); runParams.put(AbilityKey.Attacker, c);
final List<Card> otherAttackers = combat.getAttackers(); final List<Card> otherAttackers = combat.getAttackers();
otherAttackers.remove(c); otherAttackers.remove(c);
runParams.put("OtherAttackers", otherAttackers); runParams.put(AbilityKey.OtherAttackers, otherAttackers);
runParams.put("Attacked", combat.getDefenderByAttacker(c)); runParams.put(AbilityKey.Attacked, combat.getDefenderByAttacker(c));
runParams.put("DefendingPlayer", combat.getDefenderPlayerByAttacker(c)); runParams.put(AbilityKey.DefendingPlayer, combat.getDefenderPlayerByAttacker(c));
runParams.put("Defenders", combat.getDefenders()); runParams.put(AbilityKey.Defenders, combat.getDefenders());
game.getTriggerHandler().runTriggerOld(TriggerType.Attacks, runParams, false); game.getTriggerHandler().runTrigger(TriggerType.Attacks, runParams, false);
c.getDamageHistory().setCreatureAttackedThisCombat(true); c.getDamageHistory().setCreatureAttackedThisCombat(true);
c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf(); c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf();

View File

@@ -228,7 +228,7 @@ public abstract class KeywordInstance<T extends KeywordInstance<?>> implements K
result.staticAbilities = Lists.newArrayList(); result.staticAbilities = Lists.newArrayList();
for (StaticAbility sa : this.staticAbilities) { for (StaticAbility sa : this.staticAbilities) {
result.staticAbilities.add(new StaticAbility(sa, host)); result.staticAbilities.add(sa.copy(host, lki));
} }
return result; return result;

View File

@@ -27,6 +27,7 @@ import forge.util.TextUtil;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
@@ -261,6 +262,6 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public int hashCode() { public int hashCode() {
return 42 * (42 + this.getId()); return Objects.hash(ReplacementEffect.class, getId());
} }
} }

View File

@@ -205,7 +205,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
} }
@Override @Override
public int hashCode() { public int hashCode() {
return getId(); return Objects.hash(SpellAbility.class, getId());
} }
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.staticability; package forge.game.staticability;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import forge.card.MagicColor; import forge.card.MagicColor;
@@ -24,6 +25,7 @@ import forge.game.CardTraitBase;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GameStage; import forge.game.GameStage;
import forge.game.IIdentifiable;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
@@ -43,18 +45,38 @@ import forge.util.TextUtil;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
/** /**
* The Class StaticAbility. * The Class StaticAbility.
*/ */
public class StaticAbility extends CardTraitBase implements Comparable<StaticAbility> { public class StaticAbility extends CardTraitBase implements IIdentifiable, Cloneable, Comparable<StaticAbility> {
private static int maxId = 0;
private static int nextId() { return ++maxId; }
private final Set<StaticAbilityLayer> layers; private int id;
private Set<StaticAbilityLayer> layers;
private CardCollectionView ignoreEffectCards = new CardCollection(); private CardCollectionView ignoreEffectCards = new CardCollection();
private final List<Player> ignoreEffectPlayers = Lists.newArrayList(); private final List<Player> ignoreEffectPlayers = Lists.newArrayList();
private int mayPlayTurn = 0; private int mayPlayTurn = 0;
@Override
public final int getId() {
return id;
}
@Override
public int hashCode() {
return Objects.hash(StaticAbility.class, getId());
}
@Override
public boolean equals(final Object obj) {
return obj instanceof StaticAbility && this.id == ((StaticAbility) obj).id;
}
/** /**
* <p> * <p>
* Getter for the field <code>mapParams</code>. * Getter for the field <code>mapParams</code>.
@@ -228,6 +250,7 @@ public class StaticAbility extends CardTraitBase implements Comparable<StaticAbi
* the host * the host
*/ */
private StaticAbility(final Map<String, String> params, final Card host) { private StaticAbility(final Map<String, String> params, final Card host) {
this.id = nextId();
this.originalMapParams.putAll(params); this.originalMapParams.putAll(params);
this.mapParams.putAll(params); this.mapParams.putAll(params);
this.layers = this.generateLayer(); this.layers = this.generateLayer();
@@ -235,19 +258,6 @@ public class StaticAbility extends CardTraitBase implements Comparable<StaticAbi
buildCommonAttributes(host); buildCommonAttributes(host);
} }
public StaticAbility(StaticAbility stAb, Card host) {
this.originalMapParams.putAll(stAb.originalMapParams);
this.mapParams.putAll(stAb.mapParams);
this.layers = this.generateLayer();
this.hostCard = host;
this.intrinsic = stAb.intrinsic;
// Copy old sVars
this.sVars.putAll(stAb.sVars);
// but if they are References use this ones
buildCommonAttributes(host);
}
public final CardCollectionView applyContinuousAbilityBefore(final StaticAbilityLayer layer, final CardCollectionView preList) { public final CardCollectionView applyContinuousAbilityBefore(final StaticAbilityLayer layer, final CardCollectionView preList) {
if (!shouldApplyContinuousAbility(layer, false)) { if (!shouldApplyContinuousAbility(layer, false)) {
return null; return null;
@@ -769,6 +779,32 @@ public class StaticAbility extends CardTraitBase implements Comparable<StaticAbi
@Override @Override
public int compareTo(StaticAbility arg0) { public int compareTo(StaticAbility arg0) {
return getHostCard().compareTo(arg0.getHostCard()); return ComparisonChain.start()
.compare(getHostCard(),arg0.getHostCard())
.compare(getId(), arg0.getId())
.result();
}
public StaticAbility copy(Card host, final boolean lki) {
StaticAbility clone = null;
try {
clone = (StaticAbility) clone();
clone.id = lki ? id : nextId();
// dont use setHostCard to not trigger the not copied parts yet
clone.hostCard = host;
// need to clone the maps too so they can be changed
clone.originalMapParams = Maps.newHashMap(this.originalMapParams);
clone.mapParams = Maps.newHashMap(this.mapParams);
clone.sVars = Maps.newHashMap(this.sVars);
clone.layers = this.generateLayer();
clone.buildCommonAttributes(host);
} catch (final CloneNotSupportedException e) {
System.err.println(e);
}
return clone;
} }
} // end class StaticAbility } // end class StaticAbility

View File

@@ -532,7 +532,7 @@ public final class StaticAbilityContinuous {
if (addT.startsWith("AffectedX")) { if (addT.startsWith("AffectedX")) {
toughnessBonus = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, addT)); toughnessBonus = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, addT));
} }
affectedCard.addPTBoost(powerBonus, toughnessBonus, se.getTimestamp()); affectedCard.addPTBoost(powerBonus, toughnessBonus, se.getTimestamp(), stAb.getId());
} }
// add keywords // add keywords

View File

@@ -431,7 +431,7 @@ public abstract class Trigger extends TriggerReplacementBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public int hashCode() { public int hashCode() {
return 41 * (41 + this.getId()); return Objects.hash(Trigger.class, getId());
} }
/** /**

View File

@@ -2036,4 +2036,23 @@ public class GameSimulatorTest extends SimulationTestCase {
assertTrue(dimirdgAfterCopy2.isFlipped()); assertTrue(dimirdgAfterCopy2.isFlipped());
assertFalse(dimirdgAfterCopy2.getType().isLegendary()); assertFalse(dimirdgAfterCopy2.getType().isLegendary());
} }
public void testStaticMultiPump() {
Game game = initAndCreateGame();
Player p = game.getPlayers().get(1);
Card c1 = addCard("Creakwood Liege", p);
Card c2 = addCard("Creakwood Liege", p);
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
// update stats state
game.getAction().checkStateEffects(true);
assertTrue(c1.getNetPower() == 4);
assertTrue(c1.getNetToughness() == 4);
assertTrue(c2.getNetPower() == 4);
assertTrue(c2.getNetToughness() == 4);
}
} }