diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index bb8bc575f55..a56e032dc87 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1601,8 +1601,8 @@ public class ComputerUtilCard { } pumped.addNewPT(c.getCurrentPower(), c.getCurrentToughness(), timestamp); - pumped.setPTBoost(c.getPTBoostMap()); - pumped.addPTBoost(power + berserkPower, toughness, timestamp); + pumped.setPTBoost(c.getPTBoostTable()); + pumped.addPTBoost(power + berserkPower, toughness, timestamp, null); pumped.addChangedCardKeywords(kws, null, false, false, timestamp); Set types = c.getCounters().keySet(); 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 for (final Card c : list) { // remove old boost that might be copied - vCard.removePTBoost(c.getTimestamp()); for (final StaticAbility stAb : c.getStaticAbilities()) { + vCard.removePTBoost(c.getTimestamp(), stAb.getId()); final Map params = stAb.getMapParams(); if (!params.get("Mode").equals("Continuous")) { continue; @@ -1683,7 +1683,7 @@ public class ComputerUtilCard { def = AbilityUtils.calculateAmount(c, addT, stAb); } } - vCard.addPTBoost(att, def, c.getTimestamp()); + vCard.addPTBoost(att, def, c.getTimestamp(), stAb.getId()); } } } diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index 8cd20c54a26..d2ae1de2379 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -246,7 +246,7 @@ public class GameCopier { newCard.addType(type); } for (StaticAbility stAb : c.getStaticAbilities()) { - newCard.addStaticAbility(stAb); + newCard.addStaticAbility(stAb.copy(newCard, true)); } for (SpellAbility sa : c.getSpellAbilities()) { SpellAbility saCopy = sa.copy(newCard, true); @@ -277,7 +277,7 @@ public class GameCopier { // TODO: Copy the full list with timestamps. newCard.addNewPT(setPower, setToughness, newGame.getNextTimestamp()); } - newCard.setPTBoost(c.getPTBoostMap()); + newCard.setPTBoost(c.getPTBoostTable()); newCard.setDamage(c.getDamage()); newCard.setChangedCardTypes(c.getChangedCardTypesMap()); diff --git a/forge-game/src/main/java/forge/game/StaticEffect.java b/forge-game/src/main/java/forge/game/StaticEffect.java index b27ed2f3d20..8261b4d8143 100644 --- a/forge-game/src/main/java/forge/game/StaticEffect.java +++ b/forge-game/src/main/java/forge/game/StaticEffect.java @@ -798,7 +798,7 @@ public class StaticEffect { } // remove P/T bonus - affectedCard.removePTBoost(getTimestamp()); + affectedCard.removePTBoost(getTimestamp(), ability.getId()); // the view is updated in GameAction#checkStaticAbilities to avoid flickering diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index 8564a6e92bb..599e7bcc8c5 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -9,6 +9,11 @@ import java.util.Map; public enum AbilityKey { AbilityMana("AbilityMana"), Affected("Affected"), + Attach("Attach"), + AllVotes("AllVotes"), + AttachSource("AttachSource"), + AttachTarget("AttachTarget"), + Attacked("Attacked"), Attacker("Attacker"), Attackers("Attackers"), AttackingPlayer("AttackingPlayer"), @@ -16,35 +21,51 @@ public enum AbilityKey { Blocker("Blocker"), Blockers("Blockers"), Card("Card"), + Cards("Cards"), CardLKI("CardLKI"), Cause("Cause"), Causer("Causer"), Championed("Championed"), + CounterAmount("CounterAmount"), CounteredSA("CounteredSA"), + CounterType("CounterType"), + CumulativeUpkeepPaid("CumulativeUpkeepPaid"), DamageAmount("DamageAmount"), DamageSource("DamageSource"), + DamageSources("DamageSources"), DamageTarget("DamageTarget"), + DamageTargets("DamageTargets"), Defender("Defender"), + Defenders("Defenders"), DefendingPlayer("DefendingPlayer"), Destination("Destination"), + Devoured("Devoured"), + EchoPaid("EchoPaid"), + Exploited("Exploited"), Event("Event"), Fighter("Fighter"), Fizzle("Fizzle"), IsCombatDamage("IsCombatDamage"), + PayingMana("PayingMana"), Player("Player"), IndividualCostPaymentInstance("IndividualCostPaymentInstance"), MonstrosityAmount("MonstrosityAmount"), + NewCounterAmount("NewCounterAmount"), NumBlockers("NumBlockers"), + Object("Object"), Objects("Objects"), + OtherAttackers("OtherAttackers"), Origin("Origin"), OriginalController("OriginalController"), Produced("Produced"), Result("Result"), Scheme("Scheme"), + Source("Source"), SpellAbilityStackInstance("SpellAbilityStackInstance"), StackSa("StackSa"), StackSi("StackSi"), Target("Target"), + Transformer("Transformer"), Won("Won"); diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java index 010914c6775..790eed68849 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java @@ -52,7 +52,7 @@ public class PumpAllEffect extends SpellAbilityEffect { boolean redrawPT = false; if (a != 0 || d != 0) { - tgtC.addPTBoost(a, d, timestamp); + tgtC.addPTBoost(a, d, timestamp, 0); redrawPT = true; } @@ -76,7 +76,7 @@ public class PumpAllEffect extends SpellAbilityEffect { @Override public void run() { - tgtC.removePTBoost(timestamp); + tgtC.removePTBoost(timestamp, 0); tgtC.removeChangedCardKeywords(timestamp); for (String kw : hiddenkws) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java index 1c89e3a66ff..e43f7876b5d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java @@ -56,7 +56,7 @@ public class PumpEffect extends SpellAbilityEffect { } if (a != 0 || d != 0) { - gameCard.addPTBoost(a, d, timestamp); + gameCard.addPTBoost(a, d, timestamp, 0); redrawPT = true; } @@ -84,7 +84,7 @@ public class PumpEffect extends SpellAbilityEffect { @Override public void run() { - gameCard.removePTBoost(timestamp); + gameCard.removePTBoost(timestamp, 0); boolean updateText = false; updateText = gameCard.removeCanBlockAny(timestamp) || updateText; updateText = gameCard.removeCanBlockAdditional(timestamp) || updateText; diff --git a/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java index b152fdd062e..bd773d5ccbb 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java @@ -1,6 +1,7 @@ package forge.game.ability.effects; import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.event.GameEventCardRegenerated; @@ -9,8 +10,6 @@ import forge.game.trigger.TriggerType; import java.util.Map; -import com.google.common.collect.Maps; - public class RegenerationEffect extends SpellAbilityEffect { /* @@ -44,10 +43,9 @@ public class RegenerationEffect extends SpellAbilityEffect { } // Run triggers - final Map runParams = Maps.newHashMap(); - runParams.put("Card", c); - runParams.put("Cause", host); - game.getTriggerHandler().runTriggerOld(TriggerType.Regenerated, runParams, false); + final Map runParams = AbilityKey.mapFromCard(c); + runParams.put(AbilityKey.Cause, host); + game.getTriggerHandler().runTrigger(TriggerType.Regenerated, runParams, false); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/RevealEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RevealEffect.java index 369383598a1..8aefd31a571 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RevealEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RevealEffect.java @@ -1,6 +1,7 @@ package forge.game.ability.effects; import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -14,9 +15,7 @@ import forge.game.zone.ZoneType; import forge.util.Aggregates; import java.util.List; -import java.util.Map; -import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; public class RevealEffect extends SpellAbilityEffect { @@ -74,14 +73,7 @@ public class RevealEffect extends SpellAbilityEffect { game.getAction().reveal(revealed, p); for (final Card c : revealed) { - Map runParams = Maps.newHashMap(); - runParams.put("Card", c); - /* - if (sa.hasParam("MiracleCost")) { - runParams.put("Miracle", true); - } - //*/ - game.getTriggerHandler().runTriggerOld(TriggerType.Revealed, runParams, false); + game.getTriggerHandler().runTrigger(TriggerType.Revealed, AbilityKey.mapFromCard(c), false); if (sa.hasParam("RememberRevealed")) { host.addRemembered(c); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java index 25285e6d375..f4e3c887497 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java @@ -1,10 +1,10 @@ package forge.game.ability.effects; -import com.google.common.collect.Maps; import forge.card.mana.ManaCost; import forge.game.Game; import forge.game.GameActionUtil; import forge.game.GameEntityCounterTable; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.*; @@ -36,10 +36,9 @@ public class SacrificeEffect extends SpellAbilityEffect { isPaid = activator.getController().payManaOptional(card, new Cost(sa.getParam("Echo"), true), sa, "Pay Echo", ManaPaymentPurpose.Echo); } - final Map runParams = Maps.newHashMap(); - runParams.put("EchoPaid", Boolean.valueOf(isPaid)); - runParams.put("Card", card); - game.getTriggerHandler().runTriggerOld(TriggerType.PayEcho, runParams, false); + final Map runParams = AbilityKey.mapFromCard(card); + runParams.put(AbilityKey.EchoPaid, isPaid); + game.getTriggerHandler().runTrigger(TriggerType.PayEcho, runParams, false); if (isPaid || !card.getController().equals(activator)) { return; } @@ -65,11 +64,10 @@ public class SacrificeEffect extends SpellAbilityEffect { sb.append("Cumulative upkeep for ").append(card); boolean isPaid = activator.getController().payManaOptional(card, payCost, sa, sb.toString(), ManaPaymentPurpose.CumulativeUpkeep); - final Map runParams = Maps.newHashMap(); - runParams.put("CumulativeUpkeepPaid", Boolean.valueOf(isPaid)); - runParams.put("Card", card); - runParams.put("PayingMana", StringUtils.join(sa.getPayingMana(), "")); - game.getTriggerHandler().runTriggerOld(TriggerType.PayCumulativeUpkeep, runParams, false); + final Map runParams = AbilityKey.mapFromCard(card); + runParams.put(AbilityKey.CumulativeUpkeepPaid, isPaid); + runParams.put(AbilityKey.PayingMana, StringUtils.join(sa.getPayingMana(), "")); + game.getTriggerHandler().runTrigger(TriggerType.PayCumulativeUpkeep, runParams, false); if (isPaid || !card.getController().equals(activator)) { return; } @@ -147,16 +145,15 @@ public class SacrificeEffect extends SpellAbilityEffect { // Run Devour Trigger if (devour) { card.addDevoured(lKICopy); - final Map runParams = Maps.newHashMap(); - runParams.put("Devoured", sac); - game.getTriggerHandler().runTriggerOld(TriggerType.Devoured, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Devoured, sac); + game.getTriggerHandler().runTrigger(TriggerType.Devoured, runParams, false); } if (exploit) { card.addExploited(lKICopy); - final Map runParams = Maps.newHashMap(); - runParams.put("Exploited", lKICopy); - runParams.put("Card", card); - game.getTriggerHandler().runTriggerOld(TriggerType.Exploited, runParams, false); + final Map runParams = AbilityKey.mapFromCard(card); + runParams.put(AbilityKey.Exploited, lKICopy); + game.getTriggerHandler().runTrigger(TriggerType.Exploited, runParams, false); } if (wasDestroyed || wasSacrificed) { countSacrificed++; diff --git a/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java index 702e4851a2c..338378c936e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java @@ -1,8 +1,8 @@ package forge.game.ability.effects; -import com.google.common.collect.Maps; import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -46,9 +46,9 @@ public class SetInMotionEffect extends SpellAbilityEffect { game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); // Run triggers - final Map runParams = Maps.newHashMap(); - runParams.put("Scheme", controller.getActiveScheme()); - game.getTriggerHandler().runTriggerOld(TriggerType.SetInMotion, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Scheme, controller.getActiveScheme()); + game.getTriggerHandler().runTrigger(TriggerType.SetInMotion, runParams, false); } else { controller.setSchemeInMotion(); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/VoteEffect.java b/forge-game/src/main/java/forge/game/ability/effects/VoteEffect.java index 5c5e84e7c28..d4c911f24f4 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/VoteEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/VoteEffect.java @@ -5,13 +5,13 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import forge.game.ability.AbilityKey; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import forge.game.Game; 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); } } - - final Map runParams = Maps.newHashMap(); - runParams.put("AllVotes", votes); - game.getTriggerHandler().runTriggerOld(TriggerType.Vote, runParams, false); + + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.AllVotes, votes); + game.getTriggerHandler().runTrigger(TriggerType.Vote, runParams, false); List subAbs = Lists.newArrayList(); final List mostVotes = getMostVotes(votes); diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index e77e4398587..cef51f069ee 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -30,6 +30,7 @@ import forge.card.mana.ManaCost; import forge.card.mana.ManaCostParser; import forge.game.*; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.effects.CharmEffect; @@ -197,7 +198,9 @@ public class Card extends GameEntity implements Comparable { // stack of set power/toughness private Map> newPT = Maps.newTreeMap(); private Map> newPTCharacterDefining = Maps.newTreeMap(); - private Map> boostPT = Maps.newTreeMap(); + + // x=Static Avility id or 0, y=timestamp + private Table> boostPT = TreeBasedTable.create(); private String basePowerString = null; private String baseToughnessString = null; @@ -567,9 +570,9 @@ public class Card extends GameEntity implements Comparable { // Clear old dfc trigger from the trigger handler getGame().getTriggerHandler().clearInstrinsicActiveTriggers(this, null); getGame().getTriggerHandler().registerActiveTrigger(this, false); - Map runParams = Maps.newHashMap(); - runParams.put("Transformer", this); - getGame().getTriggerHandler().runTriggerOld(TriggerType.Transformed, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Transformer, this); + getGame().getTriggerHandler().runTrigger(TriggerType.Transformed, runParams, false); incrementTransformedTimestamp(); return result; @@ -687,9 +690,7 @@ public class Card extends GameEntity implements Comparable { // Run triggers getGame().getTriggerHandler().registerActiveTrigger(this, false); - final Map runParams = Maps.newTreeMap(); - runParams.put("Card", this); - getGame().getTriggerHandler().runTriggerOld(TriggerType.TurnFaceUp, runParams, false); + getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, AbilityKey.mapFromCard(this), false); } return result; } @@ -1281,18 +1282,17 @@ public class Card extends GameEntity implements Comparable { } // Run triggers - final Map runParams = Maps.newHashMap(); - runParams.put("Card", this); - runParams.put("Source", source); - runParams.put("CounterType", counterType); + final Map runParams = AbilityKey.mapFromCard(this); + runParams.put(AbilityKey.Source, source); + runParams.put(AbilityKey.CounterType, counterType); for (int i = 0; i < addAmount; i++) { - runParams.put("CounterAmount", oldValue + i + 1); - getGame().getTriggerHandler().runTriggerOld( + runParams.put(AbilityKey.CounterAmount, oldValue + i + 1); + getGame().getTriggerHandler().runTrigger( TriggerType.CounterAdded, Maps.newHashMap(runParams), false); } if (addAmount > 0) { - runParams.put("CounterAmount", addAmount); - getGame().getTriggerHandler().runTriggerOld( + runParams.put(AbilityKey.CounterAmount, addAmount); + getGame().getTriggerHandler().runTrigger( TriggerType.CounterAddedOnce, Maps.newHashMap(runParams), false); } } else { @@ -1340,10 +1340,10 @@ public class Card extends GameEntity implements Comparable { @Override public final void subtractCounter(final CounterType counterName, final int n) { - Integer oldValue = getCounters(counterName); - int newValue = oldValue == null ? 0 : Math.max(oldValue - n, 0); + int oldValue = getCounters(counterName); + int newValue = Math.max(oldValue - n, 0); - final int delta = (oldValue == null ? 0 : oldValue) - newValue; + final int delta = oldValue - newValue; if (delta == 0) { return; } int powerBonusBefore = getPowerBonusFromCounters(); @@ -1359,19 +1359,18 @@ public class Card extends GameEntity implements Comparable { } // 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 - int curCounters = oldValue == null ? 0 : oldValue; - final Map runParams = Maps.newTreeMap(); - runParams.put("Card", this); - runParams.put("CounterType", counterName); + int curCounters = oldValue; + final Map runParams = AbilityKey.mapFromCard(this); + runParams.put(AbilityKey.CounterType, counterName); for (int i = 0; i < delta && curCounters != 0; i++) { - runParams.put("NewCounterAmount", --curCounters); - getGame().getTriggerHandler().runTriggerOld(TriggerType.CounterRemoved, runParams, false); + runParams.put(AbilityKey.NewCounterAmount, --curCounters); + getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams, false); } - runParams.put("CounterAmount", delta); - getGame().getTriggerHandler().runTriggerOld(TriggerType.CounterRemovedOnce, runParams, false); + runParams.put(AbilityKey.CounterAmount, delta); + getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemovedOnce, runParams, false); } @Override @@ -2935,10 +2934,10 @@ public class Card extends GameEntity implements Comparable { getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, entity)); // run trigger - final Map runParams = Maps.newHashMap(); - runParams.put("AttachSource", this); - runParams.put("AttachTarget", entity); - getController().getGame().getTriggerHandler().runTriggerOld(TriggerType.Attached, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.AttachSource, this); + runParams.put(AbilityKey.AttachTarget, entity); + getController().getGame().getTriggerHandler().runTrigger(TriggerType.Attached, runParams, false); } @@ -2957,10 +2956,10 @@ public class Card extends GameEntity implements Comparable { getGame().fireEvent(new GameEventCardAttachment(this, entity, null)); // Run triggers - final Map runParams = Maps.newTreeMap(); - runParams.put("Attach", this); - runParams.put("Object", entity); - getGame().getTriggerHandler().runTriggerOld(TriggerType.Unattach, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Attach, this); + runParams.put(AbilityKey.Object, entity); + getGame().getTriggerHandler().runTrigger(TriggerType.Unattach, runParams, false); runUnattachCommands(); } @@ -3477,23 +3476,21 @@ public class Card extends GameEntity implements Comparable { return result; } - public void addPTBoost(final Integer power, final Integer toughness, final long timestamp) { - boostPT.put(timestamp, Pair.of(power, toughness)); + public void addPTBoost(final Integer power, final Integer toughness, final long timestamp, final Integer staticId) { + boostPT.put(staticId == null ? 0 : staticId, timestamp, Pair.of(power, toughness)); } - public void removePTBoost(final long timestamp) { - boostPT.remove(timestamp); + public void removePTBoost(final long timestamp, final Integer staticId) { + boostPT.remove(staticId, timestamp); } - public Map> getPTBoostMap() { - return ImmutableMap.copyOf(boostPT); + public Table> getPTBoostTable() { + return ImmutableTable.copyOf(boostPT); } - public void setPTBoost(Map> map) { + public void setPTBoost(Table> table) { this.boostPT.clear(); - for (Map.Entry> e : map.entrySet()) { - this.boostPT.put(e.getKey(), Pair.of(e.getValue().getLeft(), e.getValue().getRight())); - } + boostPT.putAll(table); } public final boolean isUntapped() { @@ -3516,10 +3513,9 @@ public class Card extends GameEntity implements Comparable { if (tapped) { return; } // Run triggers - final Map runParams = Maps.newTreeMap(); - runParams.put("Card", this); - runParams.put("Attacker", attacker); - getGame().getTriggerHandler().runTriggerOld(TriggerType.Taps, runParams, false); + final Map runParams = AbilityKey.mapFromCard(this); + runParams.put(AbilityKey.Attacker, attacker); + getGame().getTriggerHandler().runTrigger(TriggerType.Taps, runParams, false); setTapped(true); getGame().fireEvent(new GameEventCardTapped(this, true)); @@ -3538,9 +3534,7 @@ public class Card extends GameEntity implements Comparable { } // Run triggers - final Map runParams = Maps.newTreeMap(); - runParams.put("Card", this); - getGame().getTriggerHandler().runTriggerOld(TriggerType.Untaps, runParams, false); + getGame().getTriggerHandler().runTrigger(TriggerType.Untaps, AbilityKey.mapFromCard(this), false); for (final GameCommand var : untapCommandList) { var.run(); @@ -3971,12 +3965,8 @@ public class Card extends GameEntity implements Comparable { return null; } public final StaticAbility addStaticAbility(final StaticAbility stAb) { - return addStaticAbility(stAb, false); - } - public final StaticAbility addStaticAbility(final StaticAbility stAb, boolean intrinsic) { - final StaticAbility stAbCopy = new StaticAbility(stAb, this); - currentState.addStaticAbility(stAbCopy); - return stAbCopy; + currentState.addStaticAbility(stAb); + return stAb; } public final void removeStaticAbility(StaticAbility stAb) { currentState.removeStaticAbility(stAb); @@ -4099,13 +4089,12 @@ public class Card extends GameEntity implements Comparable { return false; } - final Map runParams = Maps.newTreeMap(); - runParams.put("Card", this); + final Map runParams = AbilityKey.mapFromCard(this); if (!isPhasedOut()) { // 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 - getGame().getTriggerHandler().runTriggerOld(TriggerType.PhaseOut, runParams, false); + getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false); } setPhasedOut(!phasedOut); @@ -4117,7 +4106,7 @@ public class Card extends GameEntity implements Comparable { if (!phasedOut) { // Just phased in, time to run the phased in trigger getGame().getTriggerHandler().registerActiveTrigger(this, false); - getGame().getTriggerHandler().runTriggerOld(TriggerType.PhaseIn, runParams, false); + getGame().getTriggerHandler().runTrigger(TriggerType.PhaseIn, runParams, false); } return true; @@ -4900,17 +4889,17 @@ public class Card extends GameEntity implements Comparable { source.addDealtDamageToThisTurn(this, damageIn); // Run triggers - final Map runParams = Maps.newTreeMap(); - runParams.put("DamageSource", source); - runParams.put("DamageTarget", this); - runParams.put("DamageAmount", damageIn); - runParams.put("IsCombatDamage", isCombat); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.DamageSource, source); + runParams.put(AbilityKey.DamageTarget, this); + runParams.put(AbilityKey.DamageAmount, damageIn); + runParams.put(AbilityKey.IsCombatDamage, 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 - runParams.put("DefendingPlayer", game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null); - getGame().getTriggerHandler().runTriggerOld(TriggerType.DamageDone, runParams, false); + runParams.put(AbilityKey.DefendingPlayer, game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null); + getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false); GameEventCardDamaged.DamageType damageType = DamageType.Normal; if (isPlaneswalker()) { @@ -5008,10 +4997,9 @@ public class Card extends GameEntity implements Comparable { exertedByPlayer.add(getController()); exertThisTurn++; view.updateExertedThisTurn(this, true); - final Map runParams = Maps.newHashMap(); - runParams.put("Card", this); - runParams.put("Player", getController()); - game.getTriggerHandler().runTriggerOld(TriggerType.Exerted, runParams, false); + final Map runParams = AbilityKey.mapFromCard(this); + runParams.put(AbilityKey.Player, getController()); + game.getTriggerHandler().runTrigger(TriggerType.Exerted, runParams, false); } public boolean isExertedBy(final Player player) { diff --git a/forge-game/src/main/java/forge/game/card/CardDamageMap.java b/forge-game/src/main/java/forge/game/card/CardDamageMap.java index f52e7e354d7..8a742dacf68 100644 --- a/forge-game/src/main/java/forge/game/card/CardDamageMap.java +++ b/forge-game/src/main/java/forge/game/card/CardDamageMap.java @@ -7,11 +7,11 @@ import java.util.Map; import com.google.common.collect.ForwardingTable; import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.collect.Table; import forge.game.GameEntity; +import forge.game.ability.AbilityKey; import forge.game.keyword.Keyword; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; @@ -34,12 +34,12 @@ public class CardDamageMap extends ForwardingTable { } if (sum > 0) { final GameEntity ge = e.getKey(); - final Map runParams = Maps.newHashMap(); - runParams.put("DamageTarget", ge); - runParams.put("DamageAmount", sum); - runParams.put("IsCombatDamage", isCombat); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.DamageTarget, ge); + runParams.put(AbilityKey.DamageAmount, sum); + 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 { sum += i; } if (sum > 0) { - final Map runParams = Maps.newHashMap(); - runParams.put("DamageSource", sourceLKI); - runParams.put("DamageTargets", Sets.newHashSet(e.getValue().keySet())); - runParams.put("DamageAmount", sum); - runParams.put("IsCombatDamage", isCombat); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.DamageSource, sourceLKI); + runParams.put(AbilityKey.DamageTargets, Sets.newHashSet(e.getValue().keySet())); + runParams.put(AbilityKey.DamageAmount, sum); + 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)) { sourceLKI.getController().gainLife(sum, sourceLKI, sa); @@ -74,13 +74,13 @@ public class CardDamageMap extends ForwardingTable { } if (sum > 0) { final GameEntity ge = e.getKey(); - final Map runParams = Maps.newHashMap(); - runParams.put("DamageTarget", ge); - runParams.put("DamageSources", Sets.newHashSet(e.getValue().keySet())); - runParams.put("DamageAmount", sum); - runParams.put("IsCombatDamage", isCombat); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.DamageTarget, ge); + runParams.put(AbilityKey.DamageSources, Sets.newHashSet(e.getValue().keySet())); + runParams.put(AbilityKey.DamageAmount, sum); + runParams.put(AbilityKey.IsCombatDamage, isCombat); - ge.getGame().getTriggerHandler().runTriggerOld(TriggerType.DamageDoneOnce, runParams, false); + ge.getGame().getTriggerHandler().runTrigger(TriggerType.DamageDoneOnce, runParams, false); } } } diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index eb9cb92e1bf..84ece1c6bdf 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -529,7 +529,7 @@ public class CardState extends GameObject { staticAbilities.clear(); for (StaticAbility sa : source.staticAbilities) { if (sa.isIntrinsic()) { - staticAbilities.add(new StaticAbility(sa, this.card)); + staticAbilities.add(sa.copy(card, lki)); } } } diff --git a/forge-game/src/main/java/forge/game/card/CardZoneTable.java b/forge-game/src/main/java/forge/game/card/CardZoneTable.java index 30dac0b5bf5..53e95605713 100644 --- a/forge-game/src/main/java/forge/game/card/CardZoneTable.java +++ b/forge-game/src/main/java/forge/game/card/CardZoneTable.java @@ -7,10 +7,10 @@ import java.util.Map; import com.google.common.collect.ForwardingTable; import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Maps; import com.google.common.collect.Table; import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; @@ -54,9 +54,9 @@ public class CardZoneTable extends ForwardingTable runParams = Maps.newHashMap(); - runParams.put("Cards", new CardZoneTable(this)); - game.getTriggerHandler().runTriggerOld(TriggerType.ChangesZoneAll, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Cards, new CardZoneTable(this)); + game.getTriggerHandler().runTrigger(TriggerType.ChangesZoneAll, runParams, false); } } diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java index 81a242bce9e..7cf10bb47a3 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -24,6 +24,7 @@ import forge.game.GameEntity; import forge.game.GameEntityCounterTable; import forge.game.GameLogEntryType; import forge.game.GameObjectMap; +import forge.game.ability.AbilityKey; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; @@ -632,11 +633,11 @@ public class Combat { defenders.add(getDefenderByAttacker(ab)); for (Card attacker : ab.getAttackers()) { // Run Unblocked Trigger - final Map runParams = Maps.newHashMap(); - runParams.put("Attacker", attacker); - runParams.put("Defender",getDefenderByAttacker(attacker)); - runParams.put("DefendingPlayer", getDefenderPlayerByAttacker(attacker)); - game.getTriggerHandler().runTriggerOld(TriggerType.AttackerUnblocked, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Attacker, attacker); + runParams.put(AbilityKey.Defender,getDefenderByAttacker(attacker)); + runParams.put(AbilityKey.DefendingPlayer, getDefenderPlayerByAttacker(attacker)); + game.getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false); } } } @@ -644,10 +645,10 @@ public class Combat { // triggers for Coveted Jewel // currently there is only one attacking player // should be updated when two-headed-giant is done - final Map runParams = Maps.newHashMap(); - runParams.put("AttackingPlayer", getAttackingPlayer()); - runParams.put("Defenders", defenders); - game.getTriggerHandler().runTriggerOld(TriggerType.AttackerUnblockedOnce, runParams, false); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.AttackingPlayer, getAttackingPlayer()); + runParams.put(AbilityKey.Defenders, defenders); + game.getTriggerHandler().runTrigger(TriggerType.AttackerUnblockedOnce, runParams, false); } } diff --git a/forge-game/src/main/java/forge/game/combat/CombatUtil.java b/forge-game/src/main/java/forge/game/combat/CombatUtil.java index 1f9f17c682c..2b17d5b3003 100644 --- a/forge-game/src/main/java/forge/game/combat/CombatUtil.java +++ b/forge-game/src/main/java/forge/game/combat/CombatUtil.java @@ -20,13 +20,13 @@ package forge.game.combat; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import forge.card.CardType; import forge.card.MagicColor; import forge.card.mana.ManaCost; import forge.game.Game; import forge.game.GameEntity; import forge.game.GlobalRuleChange; +import forge.game.ability.AbilityKey; import forge.game.card.*; import forge.game.cost.Cost; 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) { // Run triggers - final Map runParams = Maps.newHashMap(); - runParams.put("Attacker", c); + final Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.Attacker, c); final List otherAttackers = combat.getAttackers(); otherAttackers.remove(c); - runParams.put("OtherAttackers", otherAttackers); - runParams.put("Attacked", combat.getDefenderByAttacker(c)); - runParams.put("DefendingPlayer", combat.getDefenderPlayerByAttacker(c)); - runParams.put("Defenders", combat.getDefenders()); - game.getTriggerHandler().runTriggerOld(TriggerType.Attacks, runParams, false); + runParams.put(AbilityKey.OtherAttackers, otherAttackers); + runParams.put(AbilityKey.Attacked, combat.getDefenderByAttacker(c)); + runParams.put(AbilityKey.DefendingPlayer, combat.getDefenderPlayerByAttacker(c)); + runParams.put(AbilityKey.Defenders, combat.getDefenders()); + game.getTriggerHandler().runTrigger(TriggerType.Attacks, runParams, false); c.getDamageHistory().setCreatureAttackedThisCombat(true); c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf(); diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java index 50b99b5e66a..6e7adb840fb 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java @@ -228,7 +228,7 @@ public abstract class KeywordInstance> implements K result.staticAbilities = Lists.newArrayList(); for (StaticAbility sa : this.staticAbilities) { - result.staticAbilities.add(new StaticAbility(sa, host)); + result.staticAbilities.add(sa.copy(host, lki)); } return result; diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java index 34d1f58538e..fd7796a1bf3 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java @@ -27,6 +27,7 @@ import forge.util.TextUtil; import java.util.List; import java.util.Map; +import java.util.Objects; /** * TODO: Write javadoc for this type. @@ -261,6 +262,6 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { /** {@inheritDoc} */ @Override public int hashCode() { - return 42 * (42 + this.getId()); + return Objects.hash(ReplacementEffect.class, getId()); } } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index cfa028365c6..88fe88e9833 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -205,7 +205,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } @Override public int hashCode() { - return getId(); + return Objects.hash(SpellAbility.class, getId()); } @Override public boolean equals(final Object obj) { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index 21d4edff7d5..3906fe03688 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -17,6 +17,7 @@ */ package forge.game.staticability; +import com.google.common.collect.ComparisonChain; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import forge.card.MagicColor; @@ -24,6 +25,7 @@ import forge.game.CardTraitBase; import forge.game.Game; import forge.game.GameEntity; import forge.game.GameStage; +import forge.game.IIdentifiable; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; @@ -43,18 +45,38 @@ import forge.util.TextUtil; import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; /** * The Class StaticAbility. */ -public class StaticAbility extends CardTraitBase implements Comparable { +public class StaticAbility extends CardTraitBase implements IIdentifiable, Cloneable, Comparable { + private static int maxId = 0; + private static int nextId() { return ++maxId; } - private final Set layers; + private int id; + + private Set layers; private CardCollectionView ignoreEffectCards = new CardCollection(); private final List ignoreEffectPlayers = Lists.newArrayList(); 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; + } + /** *

* Getter for the field mapParams. @@ -228,6 +250,7 @@ public class StaticAbility extends CardTraitBase implements Comparable params, final Card host) { + this.id = nextId(); this.originalMapParams.putAll(params); this.mapParams.putAll(params); this.layers = this.generateLayer(); @@ -235,19 +258,6 @@ public class StaticAbility extends CardTraitBase implements Comparable