mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
Refactoring changes and other updates:
- Completely refactor continuous static effects. Layers are now implemented properly in the sense that every effect applies the relevant parts in the relevant layer, while locking in the set of cards to which it applies. - Refactor the (un)freezing of Trackable objects to a per-game Tracker object rather than static methods, to allow multiple games hosted on the same machine. - Refactor the changing of card colours to match other parts of the code (like type and P/T changing) more closely. Also get rid of some static parameters in that code. - Some changes in how split cards on the stack are handled to make them more robust. - Some more minor changes/cleanup.
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -631,6 +631,7 @@ forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java s
|
|||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java -text
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java -text
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java -text
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java -text
|
||||||
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityLayer.java -text
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityPreventDamage.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityPreventDamage.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/staticability/package-info.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/staticability/package-info.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/trigger/Trigger.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/trigger/Trigger.java svneol=native#text/plain
|
||||||
@@ -706,6 +707,7 @@ forge-game/src/main/java/forge/trackable/TrackableObject.java -text
|
|||||||
forge-game/src/main/java/forge/trackable/TrackableProperty.java -text
|
forge-game/src/main/java/forge/trackable/TrackableProperty.java -text
|
||||||
forge-game/src/main/java/forge/trackable/TrackableSerializer.java -text
|
forge-game/src/main/java/forge/trackable/TrackableSerializer.java -text
|
||||||
forge-game/src/main/java/forge/trackable/TrackableTypes.java -text
|
forge-game/src/main/java/forge/trackable/TrackableTypes.java -text
|
||||||
|
forge-game/src/main/java/forge/trackable/Tracker.java -text
|
||||||
forge-game/src/main/java/forge/util/Expressions.java -text
|
forge-game/src/main/java/forge/util/Expressions.java -text
|
||||||
forge-game/src/main/java/forge/util/MessageUtil.java -text
|
forge-game/src/main/java/forge/util/MessageUtil.java -text
|
||||||
forge-game/src/test/java/forge/game/mana/ManaCostBeingPaidTest.java -text
|
forge-game/src/test/java/forge/game/mana/ManaCostBeingPaidTest.java -text
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import forge.game.ability.ApiType;
|
|||||||
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;
|
||||||
import forge.game.card.CardColor;
|
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
@@ -41,7 +40,6 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
public class ComputerUtilMana {
|
public class ComputerUtilMana {
|
||||||
private final static boolean DEBUG_MANA_PAYMENT = false;
|
private final static boolean DEBUG_MANA_PAYMENT = false;
|
||||||
|
|
||||||
@@ -1207,14 +1205,12 @@ public class ComputerUtilMana {
|
|||||||
Card convoked = null;
|
Card convoked = null;
|
||||||
for (ManaCostShard toPay : cost) {
|
for (ManaCostShard toPay : cost) {
|
||||||
for (Card c : list) {
|
for (Card c : list) {
|
||||||
for (CardColor col : c.getColor()) {
|
final int mask = c.determineColor().getColor() & toPay.getColorMask();
|
||||||
final int mask = col.getColorMask() & toPay.getColorMask();
|
|
||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
convoked = c;
|
convoked = c;
|
||||||
convoke.put(c, toPay);
|
convoke.put(c, toPay);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (convoked != null){
|
if (convoked != null){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
@@ -27,6 +26,7 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.staticability.StaticAbilityContinuous;
|
import forge.game.staticability.StaticAbilityContinuous;
|
||||||
|
import forge.game.staticability.StaticAbilityLayer;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.TriggerHandler;
|
import forge.game.trigger.TriggerHandler;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -396,7 +396,7 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
card.addHiddenExtrinsicKeyword(k);
|
card.addHiddenExtrinsicKeyword(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
card.addColor(finalDesc, !sa.hasParam("OverwriteColors"), true);
|
card.addColor(finalDesc, !sa.hasParam("OverwriteColors"), timestamp);
|
||||||
|
|
||||||
//back to duplicating AnimateEffect.resolve
|
//back to duplicating AnimateEffect.resolve
|
||||||
//TODO will all these abilities/triggers/replacements/etc. lead to memory leaks or unintended effects?
|
//TODO will all these abilities/triggers/replacements/etc. lead to memory leaks or unintended effects?
|
||||||
@@ -462,9 +462,11 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
if (stAbs.size() > 0) {
|
if (stAbs.size() > 0) {
|
||||||
for (final String s : stAbs) {
|
for (final String s : stAbs) {
|
||||||
final String actualAbility = source.getSVar(s);
|
final String actualAbility = source.getSVar(s);
|
||||||
StaticAbility stAb = card.addStaticAbility(actualAbility);
|
final StaticAbility stAb = card.addStaticAbility(actualAbility);
|
||||||
if ("Continuous".equals(stAb.getMapParams().get("Mode"))) {
|
if ("Continuous".equals(stAb.getMapParams().get("Mode"))) {
|
||||||
StaticAbilityContinuous.applyContinuousAbility(stAb, Lists.newArrayList(card));
|
for (final StaticAbilityLayer layer : stAb.getLayers()) {
|
||||||
|
StaticAbilityContinuous.applyContinuousAbility(stAb, new CardCollection(card), layer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,10 @@ public abstract class CardTraitBase extends GameObject {
|
|||||||
return (this.suppressed || this.temporarilySuppressed);
|
return (this.suppressed || this.temporarilySuppressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final boolean isNonTempSuppressed() {
|
||||||
|
return this.suppressed;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean meetsCommonRequirements(Map<String, String> params) {
|
protected boolean meetsCommonRequirements(Map<String, String> params) {
|
||||||
final Player hostController = this.getHostCard().getController();
|
final Player hostController = this.getHostCard().getController();
|
||||||
final Game game = hostController.getGame();
|
final Game game = hostController.getGame();
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import forge.game.trigger.TriggerType;
|
|||||||
import forge.game.zone.MagicStack;
|
import forge.game.zone.MagicStack;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.trackable.Tracker;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.FCollection;
|
import forge.util.FCollection;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
@@ -103,6 +104,7 @@ public class Game {
|
|||||||
private boolean disableAutoYields;
|
private boolean disableAutoYields;
|
||||||
|
|
||||||
private final GameView view;
|
private final GameView view;
|
||||||
|
private final Tracker tracker = new Tracker();
|
||||||
|
|
||||||
private GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
private GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
||||||
public Player getPlayer(PlayerView playerView) {
|
public Player getPlayer(PlayerView playerView) {
|
||||||
@@ -178,6 +180,10 @@ public class Game {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tracker getTracker() {
|
||||||
|
return tracker;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the players who are still fighting to win.
|
* Gets the players who are still fighting to win.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package forge.game;
|
|||||||
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.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
import forge.GameCommand;
|
import forge.GameCommand;
|
||||||
@@ -39,6 +40,7 @@ import forge.game.spellability.AbilitySub;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
|
import forge.game.staticability.StaticAbilityLayer;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.PlayerZone;
|
import forge.game.zone.PlayerZone;
|
||||||
@@ -46,10 +48,10 @@ import forge.game.zone.PlayerZoneBattlefield;
|
|||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.trackable.TrackableObject;
|
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.CollectionSuppliers;
|
import forge.util.CollectionSuppliers;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
|
import forge.util.FCollection;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
import forge.util.ThreadUtil;
|
import forge.util.ThreadUtil;
|
||||||
import forge.util.Visitor;
|
import forge.util.Visitor;
|
||||||
@@ -534,9 +536,9 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void checkStaticAbilities() {
|
public final void checkStaticAbilities() {
|
||||||
checkStaticAbilities(new HashSet<Card>());
|
checkStaticAbilities(true, new CardCollection());
|
||||||
}
|
}
|
||||||
public final void checkStaticAbilities(final Set<Card> affectedCards) {
|
public final void checkStaticAbilities(final boolean runEvents, final Set<Card> affectedCards) {
|
||||||
if (game.isGameOver()) {
|
if (game.isGameOver()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -546,18 +548,19 @@ public class GameAction {
|
|||||||
game.getTriggerHandler().cleanUpTemporaryTriggers();
|
game.getTriggerHandler().cleanUpTemporaryTriggers();
|
||||||
game.getReplacementHandler().cleanUpTemporaryReplacements();
|
game.getReplacementHandler().cleanUpTemporaryReplacements();
|
||||||
|
|
||||||
for (Player p : game.getPlayers()) {
|
for (final Player p : game.getPlayers()) {
|
||||||
p.getManaPool().restoreColorReplacements();
|
p.getManaPool().restoreColorReplacements();
|
||||||
}
|
}
|
||||||
|
|
||||||
// search for cards with static abilities
|
// search for cards with static abilities
|
||||||
final ArrayList<StaticAbility> staticAbilities = new ArrayList<StaticAbility>();
|
final FCollection<StaticAbility> staticAbilities = new FCollection<StaticAbility>();
|
||||||
final List<Card> staticList = new ArrayList<Card>();
|
final CardCollection staticList = new CardCollection();
|
||||||
|
|
||||||
game.forEachCardInGame(new Visitor<Card>() {
|
game.forEachCardInGame(new Visitor<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public void visit(Card c) {
|
public void visit(final Card c) {
|
||||||
for (int i = 0; i < c.getStaticAbilities().size(); i++) {
|
for (int i = 0; i < c.getStaticAbilities().size(); i++) {
|
||||||
StaticAbility stAb = c.getStaticAbilities().get(i);
|
final StaticAbility stAb = c.getStaticAbilities().get(i);
|
||||||
if (stAb.getMapParams().get("Mode").equals("Continuous")) {
|
if (stAb.getMapParams().get("Mode").equals("Continuous")) {
|
||||||
staticAbilities.add(stAb);
|
staticAbilities.add(stAb);
|
||||||
}
|
}
|
||||||
@@ -575,23 +578,36 @@ public class GameAction {
|
|||||||
final Comparator<StaticAbility> comp = new Comparator<StaticAbility>() {
|
final Comparator<StaticAbility> comp = new Comparator<StaticAbility>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(final StaticAbility a, final StaticAbility b) {
|
public int compare(final StaticAbility a, final StaticAbility b) {
|
||||||
int layerDelta = a.getLayer() - b.getLayer();
|
return Long.compare(a.getHostCard().getTimestamp(), b.getHostCard().getTimestamp());
|
||||||
if (layerDelta != 0) return layerDelta;
|
|
||||||
|
|
||||||
long tsDelta = a.getHostCard().getTimestamp() - b.getHostCard().getTimestamp();
|
|
||||||
return tsDelta == 0 ? 0 : tsDelta > 0 ? 1 : -1;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Collections.sort(staticAbilities, comp);
|
Collections.sort(staticAbilities, comp);
|
||||||
|
|
||||||
|
final Map<StaticAbility, CardCollectionView> affectedPerAbility = Maps.newHashMap();
|
||||||
|
for (final StaticAbilityLayer layer : StaticAbilityLayer.CONTINUOUS_LAYERS) {
|
||||||
for (final StaticAbility stAb : staticAbilities) {
|
for (final StaticAbility stAb : staticAbilities) {
|
||||||
List<Card> affectedHere = stAb.applyAbility("Continuous");
|
final CardCollectionView previouslyAffected = affectedPerAbility.get(stAb);
|
||||||
if (null != affectedHere) {
|
final CardCollectionView affectedHere;
|
||||||
affectedCards.addAll(affectedHere);
|
if (previouslyAffected == null) {
|
||||||
|
affectedHere = stAb.applyContinuousAbility(layer);
|
||||||
|
if (affectedHere != null) {
|
||||||
|
affectedPerAbility.put(stAb, affectedHere);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
affectedHere = previouslyAffected;
|
||||||
|
stAb.applyContinuousAbility(layer, previouslyAffected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollectionView lands = game.getCardsIn(ZoneType.Battlefield);
|
for (final CardCollectionView affected : affectedPerAbility.values()) {
|
||||||
GameActionUtil.grantBasicLandsManaAbilities(CardLists.filter(lands, CardPredicates.Presets.LANDS));
|
if (affected != null) {
|
||||||
|
Iterables.addAll(affectedCards, affected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final CardCollection lands = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS);
|
||||||
|
GameActionUtil.grantBasicLandsManaAbilities(lands);
|
||||||
|
|
||||||
for (final Card c : staticList) {
|
for (final Card c : staticList) {
|
||||||
for (int i = 0; i < c.getStaticCommandList().size(); i++) {
|
for (int i = 0; i < c.getStaticCommandList().size(); i++) {
|
||||||
@@ -640,6 +656,10 @@ public class GameAction {
|
|||||||
|
|
||||||
final HashMap<String, Object> runParams = new HashMap<String, Object>();
|
final HashMap<String, Object> runParams = new HashMap<String, Object>();
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.Always, runParams, false);
|
game.getTriggerHandler().runTrigger(TriggerType.Always, runParams, false);
|
||||||
|
|
||||||
|
if (runEvents && !affectedCards.isEmpty()) {
|
||||||
|
game.fireEvent(new GameEventCardStatsChanged(affectedCards));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void checkStateEffects(final boolean runEvents) {
|
public final void checkStateEffects(final boolean runEvents) {
|
||||||
@@ -652,11 +672,6 @@ public class GameAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// final JFrame frame = Singletons.getView().getFrame();
|
|
||||||
// if (!frame.isDisplayable()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (game.isGameOver()) {
|
if (game.isGameOver()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -669,11 +684,11 @@ public class GameAction {
|
|||||||
|
|
||||||
final boolean refreeze = game.getStack().isFrozen();
|
final boolean refreeze = game.getStack().isFrozen();
|
||||||
game.getStack().setFrozen(true);
|
game.getStack().setFrozen(true);
|
||||||
TrackableObject.freeze(); //prevent views flickering during while updating for state-based effects
|
game.getTracker().freeze(); //prevent views flickering during while updating for state-based effects
|
||||||
|
|
||||||
// do this multiple times, sometimes creatures/permanents will survive when they shouldn't
|
// do this multiple times, sometimes creatures/permanents will survive when they shouldn't
|
||||||
for (int q = 0; q < 9; q++) {
|
for (int q = 0; q < 9; q++) {
|
||||||
checkStaticAbilities(affectedCards);
|
checkStaticAbilities(false, affectedCards);
|
||||||
boolean checkAgain = false;
|
boolean checkAgain = false;
|
||||||
|
|
||||||
for (Player p : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
@@ -690,7 +705,7 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
List<Card> noRegCreats = null;
|
List<Card> noRegCreats = null;
|
||||||
List<Card> desCreats = null;
|
List<Card> desCreats = null;
|
||||||
for (Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
||||||
if (c.isCreature()) {
|
if (c.isCreature()) {
|
||||||
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
||||||
if (c.getNetToughness() <= 0) {
|
if (c.getNetToughness() <= 0) {
|
||||||
@@ -699,8 +714,7 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
noRegCreats.add(c);
|
noRegCreats.add(c);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
}
|
} else if (c.hasKeyword("CARDNAME can't be destroyed by lethal damage unless lethal damage dealt by a single source is marked on it.")) {
|
||||||
else if (c.hasKeyword("CARDNAME can't be destroyed by lethal damage unless lethal damage dealt by a single source is marked on it.")) {
|
|
||||||
for (final Integer dmg : c.getReceivedDamageFromThisTurn().values()) {
|
for (final Integer dmg : c.getReceivedDamageFromThisTurn().values()) {
|
||||||
if (c.getNetToughness() <= dmg.intValue()) {
|
if (c.getNetToughness() <= dmg.intValue()) {
|
||||||
if (desCreats == null) {
|
if (desCreats == null) {
|
||||||
@@ -775,7 +789,7 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
} // for q=0;q<9
|
} // for q=0;q<9
|
||||||
|
|
||||||
TrackableObject.unfreeze();
|
game.getTracker().unfreeze();
|
||||||
|
|
||||||
if (runEvents && !affectedCards.isEmpty()) {
|
if (runEvents && !affectedCards.isEmpty()) {
|
||||||
game.fireEvent(new GameEventCardStatsChanged(affectedCards));
|
game.fireEvent(new GameEventCardStatsChanged(affectedCards));
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import forge.game.card.CardView;
|
|||||||
import forge.trackable.TrackableCollection;
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.trackable.TrackableObject;
|
import forge.trackable.TrackableObject;
|
||||||
import forge.trackable.TrackableProperty;
|
import forge.trackable.TrackableProperty;
|
||||||
|
import forge.trackable.Tracker;
|
||||||
|
|
||||||
public abstract class GameEntityView extends TrackableObject {
|
public abstract class GameEntityView extends TrackableObject {
|
||||||
public static GameEntityView get(GameEntity e) {
|
public static GameEntityView get(GameEntity e) {
|
||||||
@@ -21,8 +22,8 @@ public abstract class GameEntityView extends TrackableObject {
|
|||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GameEntityView(int id0) {
|
protected GameEntityView(final int id0, final Tracker tracker) {
|
||||||
super(id0);
|
super(id0, tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ public class GameView extends TrackableObject {
|
|||||||
private CombatView combatView;
|
private CombatView combatView;
|
||||||
private final Game game; //TODO: Remove this when possible before network support added
|
private final Game game; //TODO: Remove this when possible before network support added
|
||||||
|
|
||||||
public GameView(Game game0) {
|
public GameView(final Game game0) {
|
||||||
super(-1); //ID not needed
|
super(-1, game0.getTracker()); //ID not needed
|
||||||
currentGame = this;
|
currentGame = this;
|
||||||
game = game0;
|
game = game0;
|
||||||
set(TrackableProperty.WinningTeam, -1);
|
set(TrackableProperty.WinningTeam, -1);
|
||||||
@@ -138,7 +138,7 @@ public class GameView extends TrackableObject {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
combatView = new CombatView();
|
combatView = new CombatView(combat.getAttackingPlayer().getGame().getTracker());
|
||||||
for (final AttackingBand b : combat.getAttackingBands()) {
|
for (final AttackingBand b : combat.getAttackingBands()) {
|
||||||
if (b == null) continue;
|
if (b == null) continue;
|
||||||
final GameEntity defender = combat.getDefenderByAttacker(b);
|
final GameEntity defender = combat.getDefenderByAttacker(b);
|
||||||
|
|||||||
@@ -18,14 +18,23 @@
|
|||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
|
import forge.game.card.CardCollectionView;
|
||||||
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.replacement.ReplacementEffect;
|
||||||
|
import forge.game.spellability.AbilityStatic;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.staticability.StaticAbility;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* StaticEffect class.
|
* StaticEffect class.
|
||||||
@@ -35,42 +44,42 @@ import java.util.Map;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class StaticEffect {
|
public class StaticEffect {
|
||||||
|
|
||||||
private final Card source;
|
private final Card source;
|
||||||
private int keywordNumber = 0;
|
private int keywordNumber = 0;
|
||||||
private List<Card> affectedCards = new ArrayList<Card>();
|
private CardCollectionView affectedCards = new CardCollection();
|
||||||
private ArrayList<Player> affectedPlayers = new ArrayList<Player>();
|
private List<Player> affectedPlayers = Lists.newArrayList();
|
||||||
private int xValue = 0;
|
private int xValue = 0;
|
||||||
private int yValue = 0;
|
private int yValue = 0;
|
||||||
private long timestamp = -1;
|
private long timestamp = -1;
|
||||||
private HashMap<Card, Integer> xValueMap = new HashMap<Card, Integer>();
|
private Map<Card, Integer> xValueMap = Maps.newTreeMap();
|
||||||
|
|
||||||
private String chosenType;
|
private String chosenType;
|
||||||
private Map<String, String> mapParams = new HashMap<String, String>();
|
private Map<String, String> mapParams = Maps.newTreeMap();
|
||||||
|
|
||||||
// for P/T
|
// for P/T
|
||||||
private final HashMap<Card, String> originalPT = new HashMap<Card, String>();
|
private final Map<Card, String> originalPT = Maps.newTreeMap();
|
||||||
|
|
||||||
// for types
|
// for types
|
||||||
private boolean overwriteTypes = false;
|
private boolean overwriteTypes = false;
|
||||||
private boolean keepSupertype = false;
|
private boolean keepSupertype = false;
|
||||||
private boolean removeSubTypes = false;
|
private boolean removeSubTypes = false;
|
||||||
private final HashMap<Card, ArrayList<String>> types = new HashMap<Card, ArrayList<String>>();
|
private final Map<Card, List<String>> types = Maps.newTreeMap();
|
||||||
private final HashMap<Card, ArrayList<String>> originalTypes = new HashMap<Card, ArrayList<String>>();
|
private final Map<Card, List<String>> originalTypes = Maps.newTreeMap();
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
private boolean overwriteKeywords = false;
|
private boolean overwriteKeywords = false;
|
||||||
private final HashMap<Card, ArrayList<String>> originalKeywords = new HashMap<Card, ArrayList<String>>();
|
private final Map<Card, List<String>> originalKeywords = Maps.newTreeMap();
|
||||||
|
|
||||||
// for abilities
|
// for abilities
|
||||||
private boolean overwriteAbilities = false;
|
private boolean overwriteAbilities = false;
|
||||||
private final HashMap<Card, ArrayList<SpellAbility>> originalAbilities = new HashMap<Card, ArrayList<SpellAbility>>();
|
private final Map<Card, List<SpellAbility>> originalAbilities = Maps.newTreeMap();
|
||||||
|
|
||||||
// for colors
|
// for colors
|
||||||
private String colorDesc = "";
|
private String colorDesc = "";
|
||||||
private boolean overwriteColors = false;
|
private boolean overwriteColors = false;
|
||||||
private final HashMap<Card, Long> timestamps = new HashMap<Card, Long>();
|
|
||||||
|
|
||||||
public StaticEffect(Card source) {
|
StaticEffect(final Card source) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +139,7 @@ public class StaticEffect {
|
|||||||
*/
|
*/
|
||||||
public final void addOriginalAbilities(final Card c, final SpellAbility sa) {
|
public final void addOriginalAbilities(final Card c, final SpellAbility sa) {
|
||||||
if (!this.originalAbilities.containsKey(c)) {
|
if (!this.originalAbilities.containsKey(c)) {
|
||||||
final ArrayList<SpellAbility> list = new ArrayList<SpellAbility>();
|
final List<SpellAbility> list = new ArrayList<SpellAbility>();
|
||||||
list.add(sa);
|
list.add(sa);
|
||||||
this.originalAbilities.put(c, list);
|
this.originalAbilities.put(c, list);
|
||||||
} else {
|
} else {
|
||||||
@@ -148,8 +157,8 @@ public class StaticEffect {
|
|||||||
* @param s
|
* @param s
|
||||||
* a {@link java.util.ArrayList} object.
|
* a {@link java.util.ArrayList} object.
|
||||||
*/
|
*/
|
||||||
public final void addOriginalAbilities(final Card c, final ArrayList<SpellAbility> s) {
|
public final void addOriginalAbilities(final Card c, final List<SpellAbility> s) {
|
||||||
final ArrayList<SpellAbility> list = new ArrayList<SpellAbility>(s);
|
final List<SpellAbility> list = new ArrayList<SpellAbility>(s);
|
||||||
if (!this.originalAbilities.containsKey(c)) {
|
if (!this.originalAbilities.containsKey(c)) {
|
||||||
this.originalAbilities.put(c, list);
|
this.originalAbilities.put(c, list);
|
||||||
} else {
|
} else {
|
||||||
@@ -235,7 +244,7 @@ public class StaticEffect {
|
|||||||
*/
|
*/
|
||||||
public final void addOriginalKeyword(final Card c, final String s) {
|
public final void addOriginalKeyword(final Card c, final String s) {
|
||||||
if (!this.originalKeywords.containsKey(c)) {
|
if (!this.originalKeywords.containsKey(c)) {
|
||||||
final ArrayList<String> list = new ArrayList<String>();
|
final List<String> list = new ArrayList<String>();
|
||||||
list.add(s);
|
list.add(s);
|
||||||
this.originalKeywords.put(c, list);
|
this.originalKeywords.put(c, list);
|
||||||
} else {
|
} else {
|
||||||
@@ -251,10 +260,10 @@ public class StaticEffect {
|
|||||||
* @param c
|
* @param c
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @param s
|
* @param s
|
||||||
* a {@link java.util.ArrayList} object.
|
* a {@link List} object.
|
||||||
*/
|
*/
|
||||||
public final void addOriginalKeywords(final Card c, final ArrayList<String> s) {
|
public final void addOriginalKeywords(final Card c, final List<String> s) {
|
||||||
final ArrayList<String> list = new ArrayList<String>(s);
|
final List<String> list = new ArrayList<String>(s);
|
||||||
if (!this.originalKeywords.containsKey(c)) {
|
if (!this.originalKeywords.containsKey(c)) {
|
||||||
this.originalKeywords.put(c, list);
|
this.originalKeywords.put(c, list);
|
||||||
} else {
|
} else {
|
||||||
@@ -270,10 +279,10 @@ public class StaticEffect {
|
|||||||
*
|
*
|
||||||
* @param c
|
* @param c
|
||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @return a {@link java.util.ArrayList} object.
|
* @return a {@link List} object.
|
||||||
*/
|
*/
|
||||||
public final ArrayList<String> getOriginalKeywords(final Card c) {
|
public final List<String> getOriginalKeywords(final Card c) {
|
||||||
final ArrayList<String> returnList = new ArrayList<String>();
|
final List<String> returnList = new ArrayList<String>();
|
||||||
if (this.originalKeywords.containsKey(c)) {
|
if (this.originalKeywords.containsKey(c)) {
|
||||||
returnList.addAll(this.originalKeywords.get(c));
|
returnList.addAll(this.originalKeywords.get(c));
|
||||||
}
|
}
|
||||||
@@ -450,7 +459,7 @@ public class StaticEffect {
|
|||||||
*/
|
*/
|
||||||
public final void addOriginalType(final Card c, final String s) {
|
public final void addOriginalType(final Card c, final String s) {
|
||||||
if (!this.originalTypes.containsKey(c)) {
|
if (!this.originalTypes.containsKey(c)) {
|
||||||
final ArrayList<String> list = new ArrayList<String>();
|
final List<String> list = new ArrayList<String>();
|
||||||
list.add(s);
|
list.add(s);
|
||||||
this.originalTypes.put(c, list);
|
this.originalTypes.put(c, list);
|
||||||
} else {
|
} else {
|
||||||
@@ -468,8 +477,8 @@ public class StaticEffect {
|
|||||||
* @param s
|
* @param s
|
||||||
* a {@link java.util.ArrayList} object.
|
* a {@link java.util.ArrayList} object.
|
||||||
*/
|
*/
|
||||||
public final void addOriginalTypes(final Card c, final ArrayList<String> s) {
|
public final void addOriginalTypes(final Card c, final List<String> s) {
|
||||||
final ArrayList<String> list = new ArrayList<String>(s);
|
final List<String> list = new ArrayList<String>(s);
|
||||||
if (!this.originalTypes.containsKey(c)) {
|
if (!this.originalTypes.containsKey(c)) {
|
||||||
this.originalTypes.put(c, list);
|
this.originalTypes.put(c, list);
|
||||||
} else {
|
} else {
|
||||||
@@ -487,8 +496,8 @@ public class StaticEffect {
|
|||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @return a {@link java.util.ArrayList} object.
|
* @return a {@link java.util.ArrayList} object.
|
||||||
*/
|
*/
|
||||||
public final ArrayList<String> getOriginalTypes(final Card c) {
|
public final List<String> getOriginalTypes(final Card c) {
|
||||||
final ArrayList<String> returnList = new ArrayList<String>();
|
final List<String> returnList = new ArrayList<String>();
|
||||||
if (this.originalTypes.containsKey(c)) {
|
if (this.originalTypes.containsKey(c)) {
|
||||||
returnList.addAll(this.originalTypes.get(c));
|
returnList.addAll(this.originalTypes.get(c));
|
||||||
}
|
}
|
||||||
@@ -642,59 +651,6 @@ public class StaticEffect {
|
|||||||
this.overwriteColors = overwriteColors;
|
this.overwriteColors = overwriteColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>timestamps</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a {@link java.util.HashMap} object.
|
|
||||||
*/
|
|
||||||
public final HashMap<Card, Long> getTimestamps() {
|
|
||||||
return this.timestamps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* getTimestamp.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param c
|
|
||||||
* a {@link forge.game.card.Card} object.
|
|
||||||
* @return a long.
|
|
||||||
*/
|
|
||||||
public final long getTimestamp(final Card c) {
|
|
||||||
long stamp = -1;
|
|
||||||
final Long l = this.timestamps.get(c);
|
|
||||||
if (null != l) {
|
|
||||||
stamp = l.longValue();
|
|
||||||
}
|
|
||||||
return stamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* addTimestamp.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param c
|
|
||||||
* a {@link forge.game.card.Card} object.
|
|
||||||
* @param timestamp
|
|
||||||
* a long.
|
|
||||||
*/
|
|
||||||
public final void addTimestamp(final Card c, final long timestamp) {
|
|
||||||
this.timestamps.put(c, Long.valueOf(timestamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* clearTimestamps.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public final void clearTimestamps() {
|
|
||||||
this.timestamps.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Getter for the field <code>source</code>.
|
* Getter for the field <code>source</code>.
|
||||||
@@ -736,8 +692,8 @@ public class StaticEffect {
|
|||||||
*
|
*
|
||||||
* @return a {@link forge.CardList} object.
|
* @return a {@link forge.CardList} object.
|
||||||
*/
|
*/
|
||||||
public final List<Card> getAffectedCards() {
|
public final CardCollectionView getAffectedCards() {
|
||||||
return this.affectedCards;
|
return affectedCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -748,8 +704,8 @@ public class StaticEffect {
|
|||||||
* @param list
|
* @param list
|
||||||
* a {@link forge.CardList} object.
|
* a {@link forge.CardList} object.
|
||||||
*/
|
*/
|
||||||
public final void setAffectedCards(final List<Card> list) {
|
public final void setAffectedCards(final CardCollectionView list) {
|
||||||
this.affectedCards = list;
|
affectedCards = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -757,7 +713,7 @@ public class StaticEffect {
|
|||||||
*
|
*
|
||||||
* @return the affected players
|
* @return the affected players
|
||||||
*/
|
*/
|
||||||
public final ArrayList<Player> getAffectedPlayers() {
|
public final List<Player> getAffectedPlayers() {
|
||||||
return this.affectedPlayers;
|
return this.affectedPlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,4 +834,196 @@ public class StaticEffect {
|
|||||||
return this.chosenType;
|
return this.chosenType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo everything that was changed by this effect.
|
||||||
|
*
|
||||||
|
* @return a {@link CardCollectionView} of all affected cards.
|
||||||
|
*/
|
||||||
|
final CardCollectionView remove() {
|
||||||
|
final CardCollectionView affectedCards = getAffectedCards();
|
||||||
|
final List<Player> affectedPlayers = getAffectedPlayers();
|
||||||
|
final Map<String, String> params = getParams();
|
||||||
|
final Player controller = getSource().getController();
|
||||||
|
|
||||||
|
String changeColorWordsTo = null;
|
||||||
|
|
||||||
|
int powerBonus = 0;
|
||||||
|
String addP = "";
|
||||||
|
int toughnessBonus = 0;
|
||||||
|
String addT = "";
|
||||||
|
int keywordMultiplier = 1;
|
||||||
|
boolean setPT = false;
|
||||||
|
String[] addHiddenKeywords = null;
|
||||||
|
String addColors = null;
|
||||||
|
boolean removeMayLookAt = false, removeMayPlay = false;
|
||||||
|
|
||||||
|
if (params.containsKey("ChangeColorWordsTo")) {
|
||||||
|
changeColorWordsTo = params.get("ChangeColorWordsTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("SetPower") || params.containsKey("SetToughness")) {
|
||||||
|
setPT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("AddPower")) {
|
||||||
|
addP = params.get("AddPower");
|
||||||
|
if (addP.matches("[0-9][0-9]?")) {
|
||||||
|
powerBonus = Integer.valueOf(addP);
|
||||||
|
} else if (addP.equals("AffectedX")) {
|
||||||
|
// gets calculated at runtime
|
||||||
|
} else {
|
||||||
|
powerBonus = getXValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("AddToughness")) {
|
||||||
|
addT = params.get("AddToughness");
|
||||||
|
if (addT.matches("[0-9][0-9]?")) {
|
||||||
|
toughnessBonus = Integer.valueOf(addT);
|
||||||
|
} else if (addT.equals("AffectedX")) {
|
||||||
|
// gets calculated at runtime
|
||||||
|
} else {
|
||||||
|
toughnessBonus = getYValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("KeywordMultiplier")) {
|
||||||
|
String multiplier = params.get("KeywordMultiplier");
|
||||||
|
if (multiplier.equals("X")) {
|
||||||
|
keywordMultiplier = getXValue();
|
||||||
|
} else {
|
||||||
|
keywordMultiplier = Integer.valueOf(multiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("AddHiddenKeyword")) {
|
||||||
|
addHiddenKeywords = params.get("AddHiddenKeyword").split(" & ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("AddColor")) {
|
||||||
|
final String colors = params.get("AddColor");
|
||||||
|
if (colors.equals("ChosenColor")) {
|
||||||
|
addColors = CardUtil.getShortColorsString(getSource().getChosenColors());
|
||||||
|
} else {
|
||||||
|
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & "))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("SetColor")) {
|
||||||
|
final String colors = params.get("SetColor");
|
||||||
|
if (colors.equals("ChosenColor")) {
|
||||||
|
addColors = CardUtil.getShortColorsString(getSource().getChosenColors());
|
||||||
|
} else {
|
||||||
|
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & "))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("MayLookAt")) {
|
||||||
|
removeMayLookAt = true;
|
||||||
|
}
|
||||||
|
if (params.containsKey("MayPlay")) {
|
||||||
|
removeMayPlay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("IgnoreEffectCost")) {
|
||||||
|
for (final SpellAbility s : getSource().getSpellAbilities()) {
|
||||||
|
if (s instanceof AbilityStatic && s.isTemporary()) {
|
||||||
|
getSource().removeSpellAbility(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// modify players
|
||||||
|
for (final Player p : affectedPlayers) {
|
||||||
|
p.setUnlimitedHandSize(false);
|
||||||
|
p.setMaxHandSize(p.getStartingHandSize());
|
||||||
|
p.removeChangedKeywords(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// modify the affected card
|
||||||
|
for (final Card affectedCard : affectedCards) {
|
||||||
|
// Gain control
|
||||||
|
if (params.containsKey("GainControl")) {
|
||||||
|
affectedCard.removeTempController(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert changed color words
|
||||||
|
if (changeColorWordsTo != null) {
|
||||||
|
affectedCard.removeChangedTextColorWord(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove set P/T
|
||||||
|
if (!params.containsKey("CharacteristicDefining") && setPT) {
|
||||||
|
affectedCard.removeNewPT(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove P/T bonus
|
||||||
|
if (addP.startsWith("AffectedX")) {
|
||||||
|
powerBonus = getXMapValue(affectedCard);
|
||||||
|
}
|
||||||
|
if (addT.startsWith("AffectedX")) {
|
||||||
|
toughnessBonus = getXMapValue(affectedCard);
|
||||||
|
}
|
||||||
|
affectedCard.addSemiPermanentPowerBoost(powerBonus * -1);
|
||||||
|
affectedCard.addSemiPermanentToughnessBoost(toughnessBonus * -1);
|
||||||
|
|
||||||
|
// remove keywords
|
||||||
|
// TODO regular keywords currently don't try to use keyword multiplier
|
||||||
|
// (Although nothing uses it at this time)
|
||||||
|
if (params.containsKey("AddKeyword") || params.containsKey("RemoveKeyword")
|
||||||
|
|| params.containsKey("RemoveAllAbilities")) {
|
||||||
|
affectedCard.removeChangedCardKeywords(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove abilities
|
||||||
|
if (params.containsKey("AddAbility") || params.containsKey("GainsAbilitiesOf")) {
|
||||||
|
for (final SpellAbility s : affectedCard.getSpellAbilities().threadSafeIterator()) {
|
||||||
|
if (s.isTemporary()) {
|
||||||
|
affectedCard.removeSpellAbility(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addHiddenKeywords != null) {
|
||||||
|
for (final String k : addHiddenKeywords) {
|
||||||
|
for (int j = 0; j < keywordMultiplier; j++) {
|
||||||
|
affectedCard.removeHiddenExtrinsicKeyword(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove abilities
|
||||||
|
if (params.containsKey("RemoveAllAbilities")) {
|
||||||
|
for (final SpellAbility ab : affectedCard.getSpellAbilities()) {
|
||||||
|
ab.setTemporarilySuppressed(false);
|
||||||
|
}
|
||||||
|
for (final StaticAbility stA : affectedCard.getStaticAbilities()) {
|
||||||
|
stA.setTemporarilySuppressed(false);
|
||||||
|
}
|
||||||
|
for (final ReplacementEffect rE : affectedCard.getReplacementEffects()) {
|
||||||
|
rE.setTemporarilySuppressed(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove Types
|
||||||
|
if (params.containsKey("AddType") || params.containsKey("RemoveType")) {
|
||||||
|
affectedCard.removeChangedCardTypes(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove colors
|
||||||
|
if (addColors != null) {
|
||||||
|
affectedCard.removeColor(getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove may look at
|
||||||
|
if (removeMayLookAt) {
|
||||||
|
affectedCard.setMayLookAt(controller, false);
|
||||||
|
}
|
||||||
|
if (removeMayPlay) {
|
||||||
|
affectedCard.removeMayPlay(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return affectedCards;
|
||||||
|
}
|
||||||
|
|
||||||
} // end class StaticEffect
|
} // end class StaticEffect
|
||||||
|
|||||||
@@ -17,19 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.replacement.ReplacementEffect;
|
|
||||||
import forge.game.spellability.AbilityStatic;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +38,7 @@ import forge.game.staticability.StaticAbility;
|
|||||||
public class StaticEffects {
|
public class StaticEffects {
|
||||||
|
|
||||||
// **************** StaticAbility system **************************
|
// **************** StaticAbility system **************************
|
||||||
private final List<StaticEffect> staticEffects = new ArrayList<StaticEffect>();
|
private final Map<StaticAbility, StaticEffect> staticEffects = Maps.newHashMap();
|
||||||
//Global rule changes
|
//Global rule changes
|
||||||
private final Set<GlobalRuleChange> ruleChanges = EnumSet.noneOf(GlobalRuleChange.class);
|
private final Set<GlobalRuleChange> ruleChanges = EnumSet.noneOf(GlobalRuleChange.class);
|
||||||
|
|
||||||
@@ -51,17 +46,17 @@ public class StaticEffects {
|
|||||||
ruleChanges.clear();
|
ruleChanges.clear();
|
||||||
|
|
||||||
// remove all static effects
|
// remove all static effects
|
||||||
for (final StaticEffect se : staticEffects) {
|
for (final StaticEffect se : staticEffects.values()) {
|
||||||
affectedCards.addAll(removeStaticEffect(se));
|
Iterables.addAll(affectedCards, se.remove());
|
||||||
}
|
}
|
||||||
this.staticEffects.clear();
|
this.staticEffects.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGlobalRuleChange(GlobalRuleChange change) {
|
public void setGlobalRuleChange(final GlobalRuleChange change) {
|
||||||
this.ruleChanges.add(change);
|
this.ruleChanges.add(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getGlobalRuleChange(GlobalRuleChange change) {
|
public boolean getGlobalRuleChange(final GlobalRuleChange change) {
|
||||||
return this.ruleChanges.contains(change);
|
return this.ruleChanges.contains(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,202 +66,15 @@ public class StaticEffects {
|
|||||||
* @param staticEffect
|
* @param staticEffect
|
||||||
* a {@link StaticEffect}.
|
* a {@link StaticEffect}.
|
||||||
*/
|
*/
|
||||||
public final void addStaticEffect(final StaticEffect staticEffect) {
|
public final StaticEffect getStaticEffect(final StaticAbility staticAbility) {
|
||||||
this.staticEffects.add(staticEffect);
|
final StaticEffect currentEffect = staticEffects.get(staticAbility);
|
||||||
|
if (currentEffect != null) {
|
||||||
|
return currentEffect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
final StaticEffect newEffect = new StaticEffect(staticAbility.getHostCard());
|
||||||
* Remove a static effect from the list of static effects and undo everything that was changed by the effect.
|
this.staticEffects.put(staticAbility, newEffect);
|
||||||
*
|
return newEffect;
|
||||||
* @param se
|
|
||||||
* a {@link StaticEffect}.
|
|
||||||
*/
|
|
||||||
private static final List<Card> removeStaticEffect(final StaticEffect se) {
|
|
||||||
final List<Card> affectedCards = se.getAffectedCards();
|
|
||||||
final ArrayList<Player> affectedPlayers = se.getAffectedPlayers();
|
|
||||||
final Map<String, String> params = se.getParams();
|
|
||||||
final Player controller = se.getSource().getController();
|
|
||||||
|
|
||||||
String changeColorWordsTo = null;
|
|
||||||
|
|
||||||
int powerBonus = 0;
|
|
||||||
String addP = "";
|
|
||||||
int toughnessBonus = 0;
|
|
||||||
String addT = "";
|
|
||||||
int keywordMultiplier = 1;
|
|
||||||
boolean setPT = false;
|
|
||||||
String[] addHiddenKeywords = null;
|
|
||||||
String addColors = null;
|
|
||||||
boolean removeMayLookAt = false, removeMayPlay = false;
|
|
||||||
|
|
||||||
if (params.containsKey("ChangeColorWordsTo")) {
|
|
||||||
changeColorWordsTo = params.get("ChangeColorWordsTo");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("SetPower") || params.containsKey("SetToughness")) {
|
|
||||||
setPT = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("AddPower")) {
|
|
||||||
addP = params.get("AddPower");
|
|
||||||
if (addP.matches("[0-9][0-9]?")) {
|
|
||||||
powerBonus = Integer.valueOf(addP);
|
|
||||||
} else if (addP.equals("AffectedX")) {
|
|
||||||
// gets calculated at runtime
|
|
||||||
} else {
|
|
||||||
powerBonus = se.getXValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("AddToughness")) {
|
|
||||||
addT = params.get("AddToughness");
|
|
||||||
if (addT.matches("[0-9][0-9]?")) {
|
|
||||||
toughnessBonus = Integer.valueOf(addT);
|
|
||||||
} else if (addT.equals("AffectedX")) {
|
|
||||||
// gets calculated at runtime
|
|
||||||
} else {
|
|
||||||
toughnessBonus = se.getYValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("KeywordMultiplier")) {
|
|
||||||
String multiplier = params.get("KeywordMultiplier");
|
|
||||||
if (multiplier.equals("X")) {
|
|
||||||
keywordMultiplier = se.getXValue();
|
|
||||||
} else {
|
|
||||||
keywordMultiplier = Integer.valueOf(multiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("AddHiddenKeyword")) {
|
|
||||||
addHiddenKeywords = params.get("AddHiddenKeyword").split(" & ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("AddColor")) {
|
|
||||||
final String colors = params.get("AddColor");
|
|
||||||
if (colors.equals("ChosenColor")) {
|
|
||||||
addColors = CardUtil.getShortColorsString(se.getSource().getChosenColors());
|
|
||||||
} else {
|
|
||||||
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & "))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("SetColor")) {
|
|
||||||
final String colors = params.get("SetColor");
|
|
||||||
if (colors.equals("ChosenColor")) {
|
|
||||||
addColors = CardUtil.getShortColorsString(se.getSource().getChosenColors());
|
|
||||||
} else {
|
|
||||||
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & "))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("MayLookAt")) {
|
|
||||||
removeMayLookAt = true;
|
|
||||||
}
|
|
||||||
if (params.containsKey("MayPlay")) {
|
|
||||||
removeMayPlay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("IgnoreEffectCost")) {
|
|
||||||
for (final SpellAbility s : se.getSource().getSpellAbilities()) {
|
|
||||||
if (s instanceof AbilityStatic && s.isTemporary()) {
|
|
||||||
se.getSource().removeSpellAbility(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify players
|
|
||||||
for (final Player p : affectedPlayers) {
|
|
||||||
p.setUnlimitedHandSize(false);
|
|
||||||
p.setMaxHandSize(p.getStartingHandSize());
|
|
||||||
p.removeChangedKeywords(se.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify the affected card
|
|
||||||
for (final Card affectedCard : affectedCards) {
|
|
||||||
// Gain control
|
|
||||||
if (params.containsKey("GainControl")) {
|
|
||||||
affectedCard.removeTempController(se.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Revert changed color words
|
|
||||||
if (changeColorWordsTo != null) {
|
|
||||||
affectedCard.removeChangedTextColorWord(se.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove set P/T
|
|
||||||
if (!params.containsKey("CharacteristicDefining") && setPT) {
|
|
||||||
affectedCard.removeNewPT(se.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove P/T bonus
|
|
||||||
if (addP.startsWith("AffectedX")) {
|
|
||||||
powerBonus = se.getXMapValue(affectedCard);
|
|
||||||
}
|
|
||||||
if (addT.startsWith("AffectedX")) {
|
|
||||||
toughnessBonus = se.getXMapValue(affectedCard);
|
|
||||||
}
|
|
||||||
affectedCard.addSemiPermanentPowerBoost(powerBonus * -1);
|
|
||||||
affectedCard.addSemiPermanentToughnessBoost(toughnessBonus * -1);
|
|
||||||
|
|
||||||
// remove keywords
|
|
||||||
// TODO regular keywords currently don't try to use keyword multiplier
|
|
||||||
// (Although nothing uses it at this time)
|
|
||||||
if (params.containsKey("AddKeyword") || params.containsKey("RemoveKeyword")
|
|
||||||
|| params.containsKey("RemoveAllAbilities")) {
|
|
||||||
affectedCard.removeChangedCardKeywords(se.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove abilities
|
|
||||||
if (params.containsKey("AddAbility") || params.containsKey("GainsAbilitiesOf")) {
|
|
||||||
for (final SpellAbility s : affectedCard.getSpellAbilities().threadSafeIterator()) {
|
|
||||||
if (s.isTemporary()) {
|
|
||||||
affectedCard.removeSpellAbility(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addHiddenKeywords != null) {
|
|
||||||
for (final String k : addHiddenKeywords) {
|
|
||||||
for (int j = 0; j < keywordMultiplier; j++) {
|
|
||||||
affectedCard.removeHiddenExtrinsicKeyword(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove abilities
|
|
||||||
if (params.containsKey("RemoveAllAbilities")) {
|
|
||||||
for (final SpellAbility ab : affectedCard.getSpellAbilities()) {
|
|
||||||
ab.setTemporarilySuppressed(false);
|
|
||||||
}
|
|
||||||
for (final StaticAbility stA : affectedCard.getStaticAbilities()) {
|
|
||||||
stA.setTemporarilySuppressed(false);
|
|
||||||
}
|
|
||||||
for (final ReplacementEffect rE : affectedCard.getReplacementEffects()) {
|
|
||||||
rE.setTemporarilySuppressed(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove Types
|
|
||||||
if (params.containsKey("AddType") || params.containsKey("RemoveType")) {
|
|
||||||
affectedCard.removeChangedCardTypes(se.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove colors
|
|
||||||
if (addColors != null) {
|
|
||||||
affectedCard.removeColor(addColors, affectedCard, !se.isOverwriteColors(),
|
|
||||||
se.getTimestamp(affectedCard));
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove may look at
|
|
||||||
if (removeMayLookAt) {
|
|
||||||
affectedCard.setMayLookAt(controller, false);
|
|
||||||
}
|
|
||||||
if (removeMayPlay) {
|
|
||||||
affectedCard.removeMayPlay(controller);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
se.clearTimestamps();
|
|
||||||
return affectedCards;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,8 +145,8 @@ public class AnimateAllEffect extends AnimateEffectBase {
|
|||||||
list = CardLists.getValidCards(list, valid.split(","), host.getController(), host);
|
list = CardLists.getValidCards(list, valid.split(","), host.getController(), host);
|
||||||
|
|
||||||
for (final Card c : list) {
|
for (final Card c : list) {
|
||||||
final long colorTimestamp = doAnimate(c, sa, power, toughness, types, removeTypes,
|
doAnimate(c, sa, power, toughness, types, removeTypes, finalDesc,
|
||||||
finalDesc, keywords, removeKeywords, hiddenKeywords, timestamp);
|
keywords, removeKeywords, hiddenKeywords, timestamp);
|
||||||
|
|
||||||
// give abilities
|
// give abilities
|
||||||
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
|
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
|
||||||
@@ -232,8 +232,9 @@ public class AnimateAllEffect extends AnimateEffectBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
doUnanimate(c, sa, finalDesc, hiddenKeywords, addedAbilities, addedTriggers, addedReplacements,
|
doUnanimate(c, sa, finalDesc, hiddenKeywords,
|
||||||
colorTimestamp, false, removedAbilities, timestamp);
|
addedAbilities, addedTriggers, addedReplacements,
|
||||||
|
false, removedAbilities, timestamp);
|
||||||
|
|
||||||
// give back suppressed triggers
|
// give back suppressed triggers
|
||||||
for (final Trigger t : removedTriggers) {
|
for (final Trigger t : removedTriggers) {
|
||||||
|
|||||||
@@ -80,17 +80,17 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
types.add(source.getChosenType());
|
types.add(source.getChosenType());
|
||||||
}
|
}
|
||||||
|
|
||||||
final ArrayList<String> keywords = new ArrayList<String>();
|
final List<String> keywords = new ArrayList<String>();
|
||||||
if (sa.hasParam("Keywords")) {
|
if (sa.hasParam("Keywords")) {
|
||||||
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
|
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
final ArrayList<String> removeKeywords = new ArrayList<String>();
|
final List<String> removeKeywords = new ArrayList<String>();
|
||||||
if (sa.hasParam("RemoveKeywords")) {
|
if (sa.hasParam("RemoveKeywords")) {
|
||||||
removeKeywords.addAll(Arrays.asList(sa.getParam("RemoveKeywords").split(" & ")));
|
removeKeywords.addAll(Arrays.asList(sa.getParam("RemoveKeywords").split(" & ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
final ArrayList<String> hiddenKeywords = new ArrayList<String>();
|
final List<String> hiddenKeywords = new ArrayList<String>();
|
||||||
if (sa.hasParam("HiddenKeywords")) {
|
if (sa.hasParam("HiddenKeywords")) {
|
||||||
hiddenKeywords.addAll(Arrays.asList(sa.getParam("HiddenKeywords").split(" & ")));
|
hiddenKeywords.addAll(Arrays.asList(sa.getParam("HiddenKeywords").split(" & ")));
|
||||||
}
|
}
|
||||||
@@ -117,31 +117,31 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
final String finalDesc = tmpDesc;
|
final String finalDesc = tmpDesc;
|
||||||
|
|
||||||
// abilities to add to the animated being
|
// abilities to add to the animated being
|
||||||
final ArrayList<String> abilities = new ArrayList<String>();
|
final List<String> abilities = new ArrayList<String>();
|
||||||
if (sa.hasParam("Abilities")) {
|
if (sa.hasParam("Abilities")) {
|
||||||
abilities.addAll(Arrays.asList(sa.getParam("Abilities").split(",")));
|
abilities.addAll(Arrays.asList(sa.getParam("Abilities").split(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// replacement effects to add to the animated being
|
// replacement effects to add to the animated being
|
||||||
final ArrayList<String> replacements = new ArrayList<String>();
|
final List<String> replacements = new ArrayList<String>();
|
||||||
if (sa.hasParam("Replacements")) {
|
if (sa.hasParam("Replacements")) {
|
||||||
replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(",")));
|
replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// triggers to add to the animated being
|
// triggers to add to the animated being
|
||||||
final ArrayList<String> triggers = new ArrayList<String>();
|
final List<String> triggers = new ArrayList<String>();
|
||||||
if (sa.hasParam("Triggers")) {
|
if (sa.hasParam("Triggers")) {
|
||||||
triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(",")));
|
triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// static abilities to add to the animated being
|
// static abilities to add to the animated being
|
||||||
final ArrayList<String> stAbs = new ArrayList<String>();
|
final List<String> stAbs = new ArrayList<String>();
|
||||||
if (sa.hasParam("staticAbilities")) {
|
if (sa.hasParam("staticAbilities")) {
|
||||||
stAbs.addAll(Arrays.asList(sa.getParam("staticAbilities").split(",")));
|
stAbs.addAll(Arrays.asList(sa.getParam("staticAbilities").split(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// sVars to add to the animated being
|
// sVars to add to the animated being
|
||||||
final ArrayList<String> sVars = new ArrayList<String>();
|
final List<String> sVars = new ArrayList<String>();
|
||||||
if (sa.hasParam("sVars")) {
|
if (sa.hasParam("sVars")) {
|
||||||
sVars.addAll(Arrays.asList(sa.getParam("sVars").split(",")));
|
sVars.addAll(Arrays.asList(sa.getParam("sVars").split(",")));
|
||||||
}
|
}
|
||||||
@@ -149,11 +149,11 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
List<Card> tgts = getTargetCards(sa);
|
List<Card> tgts = getTargetCards(sa);
|
||||||
|
|
||||||
for (final Card c : tgts) {
|
for (final Card c : tgts) {
|
||||||
final long colorTimestamp = doAnimate(c, sa, power, toughness, types, removeTypes,
|
doAnimate(c, sa, power, toughness, types, removeTypes, finalDesc,
|
||||||
finalDesc, keywords, removeKeywords, hiddenKeywords, timestamp);
|
keywords, removeKeywords, hiddenKeywords, timestamp);
|
||||||
|
|
||||||
// remove abilities
|
// remove abilities
|
||||||
final ArrayList<SpellAbility> removedAbilities = new ArrayList<SpellAbility>();
|
final List<SpellAbility> removedAbilities = new ArrayList<SpellAbility>();
|
||||||
boolean clearAbilities = sa.hasParam("OverwriteAbilities");
|
boolean clearAbilities = sa.hasParam("OverwriteAbilities");
|
||||||
boolean clearSpells = sa.hasParam("OverwriteSpells");
|
boolean clearSpells = sa.hasParam("OverwriteSpells");
|
||||||
boolean removeAll = sa.hasParam("RemoveAllAbilities");
|
boolean removeAll = sa.hasParam("RemoveAllAbilities");
|
||||||
@@ -174,7 +174,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// give abilities
|
// give abilities
|
||||||
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
|
final List<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
|
||||||
if (abilities.size() > 0) {
|
if (abilities.size() > 0) {
|
||||||
for (final String s : abilities) {
|
for (final String s : abilities) {
|
||||||
final String actualAbility = source.getSVar(s);
|
final String actualAbility = source.getSVar(s);
|
||||||
@@ -185,7 +185,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grant triggers
|
// Grant triggers
|
||||||
final ArrayList<Trigger> addedTriggers = new ArrayList<Trigger>();
|
final List<Trigger> addedTriggers = new ArrayList<Trigger>();
|
||||||
if (triggers.size() > 0) {
|
if (triggers.size() > 0) {
|
||||||
for (final String s : triggers) {
|
for (final String s : triggers) {
|
||||||
final String actualTrigger = source.getSVar(s);
|
final String actualTrigger = source.getSVar(s);
|
||||||
@@ -195,7 +195,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// give replacement effects
|
// give replacement effects
|
||||||
final ArrayList<ReplacementEffect> addedReplacements = new ArrayList<ReplacementEffect>();
|
final List<ReplacementEffect> addedReplacements = new ArrayList<ReplacementEffect>();
|
||||||
if (replacements.size() > 0) {
|
if (replacements.size() > 0) {
|
||||||
for (final String s : replacements) {
|
for (final String s : replacements) {
|
||||||
final String actualReplacement = source.getSVar(s);
|
final String actualReplacement = source.getSVar(s);
|
||||||
@@ -205,7 +205,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// suppress triggers from the animated card
|
// suppress triggers from the animated card
|
||||||
final ArrayList<Trigger> removedTriggers = new ArrayList<Trigger>();
|
final List<Trigger> removedTriggers = new ArrayList<Trigger>();
|
||||||
if (sa.hasParam("OverwriteTriggers") || removeAll) {
|
if (sa.hasParam("OverwriteTriggers") || removeAll) {
|
||||||
final FCollectionView<Trigger> triggersToRemove = c.getTriggers();
|
final FCollectionView<Trigger> triggersToRemove = c.getTriggers();
|
||||||
for (final Trigger trigger : triggersToRemove) {
|
for (final Trigger trigger : triggersToRemove) {
|
||||||
@@ -238,7 +238,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// suppress static abilities from the animated card
|
// suppress static abilities from the animated card
|
||||||
final ArrayList<StaticAbility> removedStatics = new ArrayList<StaticAbility>();
|
final List<StaticAbility> removedStatics = new ArrayList<StaticAbility>();
|
||||||
if (sa.hasParam("OverwriteStatics") || removeAll) {
|
if (sa.hasParam("OverwriteStatics") || removeAll) {
|
||||||
final FCollectionView<StaticAbility> staticsToRemove = c.getStaticAbilities();
|
final FCollectionView<StaticAbility> staticsToRemove = c.getStaticAbilities();
|
||||||
for (final StaticAbility stAb : staticsToRemove) {
|
for (final StaticAbility stAb : staticsToRemove) {
|
||||||
@@ -248,7 +248,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// suppress static abilities from the animated card
|
// suppress static abilities from the animated card
|
||||||
final ArrayList<ReplacementEffect> removedReplacements = new ArrayList<ReplacementEffect>();
|
final List<ReplacementEffect> removedReplacements = new ArrayList<ReplacementEffect>();
|
||||||
if (sa.hasParam("OverwriteReplacements") || removeAll) {
|
if (sa.hasParam("OverwriteReplacements") || removeAll) {
|
||||||
for (final ReplacementEffect re : c.getReplacementEffects()) {
|
for (final ReplacementEffect re : c.getReplacementEffects()) {
|
||||||
re.setTemporarilySuppressed(true);
|
re.setTemporarilySuppressed(true);
|
||||||
@@ -270,8 +270,9 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
doUnanimate(c, sa, finalDesc, hiddenKeywords, addedAbilities, addedTriggers, addedReplacements,
|
doUnanimate(c, sa, finalDesc, hiddenKeywords,
|
||||||
colorTimestamp, givesStAbs, removedAbilities, timestamp);
|
addedAbilities, addedTriggers, addedReplacements,
|
||||||
|
givesStAbs, removedAbilities, timestamp);
|
||||||
|
|
||||||
game.fireEvent(new GameEventCardStatsChanged(c));
|
game.fireEvent(new GameEventCardStatsChanged(c));
|
||||||
// give back suppressed triggers
|
// give back suppressed triggers
|
||||||
@@ -354,11 +355,11 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final boolean permanent = sa.hasParam("Permanent");
|
final boolean permanent = sa.hasParam("Permanent");
|
||||||
final ArrayList<String> types = new ArrayList<String>();
|
final List<String> types = new ArrayList<String>();
|
||||||
if (sa.hasParam("Types")) {
|
if (sa.hasParam("Types")) {
|
||||||
types.addAll(Arrays.asList(sa.getParam("Types").split(",")));
|
types.addAll(Arrays.asList(sa.getParam("Types").split(",")));
|
||||||
}
|
}
|
||||||
final ArrayList<String> keywords = new ArrayList<String>();
|
final List<String> keywords = new ArrayList<String>();
|
||||||
if (sa.hasParam("Keywords")) {
|
if (sa.hasParam("Keywords")) {
|
||||||
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
|
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
|
||||||
}
|
}
|
||||||
@@ -370,7 +371,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
keywords.remove(k);
|
keywords.remove(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final ArrayList<String> colors = new ArrayList<String>();
|
final List<String> colors = new ArrayList<String>();
|
||||||
if (sa.hasParam("Colors")) {
|
if (sa.hasParam("Colors")) {
|
||||||
colors.addAll(Arrays.asList(sa.getParam("Colors").split(",")));
|
colors.addAll(Arrays.asList(sa.getParam("Colors").split(",")));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ import forge.game.staticability.StaticAbility;
|
|||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
||||||
long doAnimate(final Card c, final SpellAbility sa, final int power, final int toughness,
|
void doAnimate(final Card c, final SpellAbility sa, final int power, final int toughness,
|
||||||
final CardType addType, final CardType removeType, final String colors,
|
final CardType addType, final CardType removeType, final String colors,
|
||||||
final ArrayList<String> keywords, final ArrayList<String> removeKeywords,
|
final List<String> keywords, final List<String> removeKeywords,
|
||||||
final ArrayList<String> hiddenKeywords, final long timestamp) {
|
final List<String> hiddenKeywords, final long timestamp) {
|
||||||
|
|
||||||
boolean removeSuperTypes = false;
|
boolean removeSuperTypes = false;
|
||||||
boolean removeCardTypes = false;
|
boolean removeCardTypes = false;
|
||||||
@@ -84,8 +85,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
c.addHiddenExtrinsicKeyword(k);
|
c.addHiddenExtrinsicKeyword(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
final long colorTimestamp = c.addColor(colors, !sa.hasParam("OverwriteColors"), true);
|
c.addColor(colors, !sa.hasParam("OverwriteColors"), timestamp);
|
||||||
return colorTimestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,10 +113,9 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
* a long.
|
* a long.
|
||||||
*/
|
*/
|
||||||
void doUnanimate(final Card c, SpellAbility sa, final String colorDesc,
|
void doUnanimate(final Card c, SpellAbility sa, final String colorDesc,
|
||||||
final ArrayList<String> hiddenKeywords, final ArrayList<SpellAbility> addedAbilities,
|
final List<String> hiddenKeywords, final List<SpellAbility> addedAbilities,
|
||||||
final ArrayList<Trigger> addedTriggers, final ArrayList<ReplacementEffect> addedReplacements,
|
final List<Trigger> addedTriggers, final List<ReplacementEffect> addedReplacements,
|
||||||
final long colorTimestamp, final boolean givesStAbs,
|
final boolean givesStAbs, final List<SpellAbility> removedAbilities, final long timestamp) {
|
||||||
final ArrayList<SpellAbility> removedAbilities, final long timestamp) {
|
|
||||||
|
|
||||||
c.removeNewPT(timestamp);
|
c.removeNewPT(timestamp);
|
||||||
|
|
||||||
@@ -132,7 +131,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
|
|||||||
c.removeChangedCardTypes(timestamp);
|
c.removeChangedCardTypes(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
c.removeColor(colorDesc, c, !sa.hasParam("OverwriteColors"), colorTimestamp);
|
c.removeColor(timestamp);
|
||||||
|
|
||||||
for (final String k : hiddenKeywords) {
|
for (final String k : hiddenKeywords) {
|
||||||
c.removeHiddenExtrinsicKeyword(k);
|
c.removeHiddenExtrinsicKeyword(k);
|
||||||
|
|||||||
@@ -402,9 +402,8 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
hostCard.clearRemembered();
|
hostCard.clearRemembered();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean optional = sa.hasParam("Optional");
|
final boolean optional = sa.hasParam("Optional");
|
||||||
|
final long ts = game.getNextTimestamp();
|
||||||
long ts = game.getNextTimestamp();
|
|
||||||
|
|
||||||
for (final Card tgtC : tgtCards) {
|
for (final Card tgtC : tgtCards) {
|
||||||
if (tgt != null && tgtC.isInPlay() && !tgtC.canBeTargetedBy(sa)) {
|
if (tgt != null && tgtC.isInPlay() && !tgtC.canBeTargetedBy(sa)) {
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ public class CloneEffect extends SpellAbilityEffect {
|
|||||||
shortColors = CardUtil.getShortColorsString(Arrays.asList(colors.split(",")));
|
shortColors = CardUtil.getShortColorsString(Arrays.asList(colors.split(",")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tgtCard.addColor(shortColors, !sa.hasParam("OverwriteColors"), true);
|
tgtCard.addColor(shortColors, !sa.hasParam("OverwriteColors"), tgtCard.getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class EffectEffect extends SpellAbilityEffect {
|
|||||||
eff.setToken(true); // Set token to true, so when leaving play it gets nuked
|
eff.setToken(true); // Set token to true, so when leaving play it gets nuked
|
||||||
eff.setOwner(controller);
|
eff.setOwner(controller);
|
||||||
eff.setImageKey(sa.hasParam("Image") ? ImageKeys.getTokenKey(sa.getParam("Image")) : hostCard.getImageKey());
|
eff.setImageKey(sa.hasParam("Image") ? ImageKeys.getTokenKey(sa.getParam("Image")) : hostCard.getImageKey());
|
||||||
eff.setColor(hostCard.getColor());
|
eff.setColor(hostCard.determineColor().getColor());
|
||||||
eff.setImmutable(true);
|
eff.setImmutable(true);
|
||||||
eff.setEffectSource(hostCard);
|
eff.setEffectSource(hostCard);
|
||||||
|
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
game.addCard(id0, this);
|
game.addCard(id0, this);
|
||||||
}
|
}
|
||||||
paperCard = paperCard0;
|
paperCard = paperCard0;
|
||||||
view = new CardView(id0);
|
view = new CardView(id0, game == null ? null : game.getTracker());
|
||||||
currentState = new CardState(view.getCurrentState(), this);
|
currentState = new CardState(view.getCurrentState(), this);
|
||||||
states.put(CardStateName.Original, currentState);
|
states.put(CardStateName.Original, currentState);
|
||||||
states.put(CardStateName.FaceDown, CardUtil.getFaceDownCharacteristic(this));
|
states.put(CardStateName.FaceDown, CardUtil.getFaceDownCharacteristic(this));
|
||||||
@@ -1080,44 +1080,19 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return currentState.getManaCost();
|
return currentState.getManaCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addColor(String s) {
|
public final void addColor(final String s, final boolean addToColors, final long timestamp) {
|
||||||
if (s.equals("")) {
|
currentState.addColor(s, addToColors, timestamp);
|
||||||
s = "0";
|
|
||||||
}
|
|
||||||
ManaCost mc = new ManaCost(new ManaCostParser(s));
|
|
||||||
currentState.getCardColor().add(new CardColor(mc.getColorProfile()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final long addColor(final String s, final boolean addToColors, final boolean bIncrease) {
|
public final void removeColor(final long timestamp) {
|
||||||
if (bIncrease) {
|
currentState.removeColor(timestamp);
|
||||||
CardColor.increaseTimestamp();
|
|
||||||
}
|
|
||||||
currentState.getCardColor().add(new CardColor(s, addToColors));
|
|
||||||
currentState.getView().updateColors(this);
|
|
||||||
return CardColor.getTimestamp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void removeColor(final String s, final Card c, final boolean addTo, final long timestampIn) {
|
public final void setColor(final byte color) {
|
||||||
CardColor removeCol = null;
|
currentState.setColor(new CardColor(color));
|
||||||
for (final CardColor cc : currentState.getCardColor()) {
|
|
||||||
if (cc.equals(s, c, addTo, timestampIn)) {
|
|
||||||
removeCol = cc;
|
|
||||||
}
|
}
|
||||||
}
|
public final void setColor(final String color) {
|
||||||
|
currentState.setColor(new CardColor(color));
|
||||||
if (removeCol != null) {
|
|
||||||
currentState.getCardColor().remove(removeCol);
|
|
||||||
currentState.getView().updateColors(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setColor(final Iterable<CardColor> colors) {
|
|
||||||
currentState.setCardColor(colors);
|
|
||||||
currentState.getView().updateColors(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Iterable<CardColor> getColor() {
|
|
||||||
return currentState.getCardColor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ColorSet determineColor() {
|
public final ColorSet determineColor() {
|
||||||
@@ -2441,7 +2416,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<Long, CardChangedType> getChangedCardTypes() {
|
public Map<Long, CardChangedType> getChangedCardTypes() {
|
||||||
return changedCardTypes;
|
return Collections.unmodifiableMap(changedCardTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addChangedCardTypes(final CardType addType, final CardType removeType,
|
public final void addChangedCardTypes(final CardType addType, final CardType removeType,
|
||||||
@@ -3212,14 +3187,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
String name = "Morph";
|
if (getView() == null) {
|
||||||
if (!isFaceDown()) {
|
return getPaperCard().getName();
|
||||||
name = getName();
|
|
||||||
if (StringUtils.isEmpty(name) && paperCard != null) {
|
|
||||||
name = paperCard.getName(); //make it possible to see likely card name before it's set
|
|
||||||
}
|
}
|
||||||
}
|
return getView().toString();
|
||||||
return name + " (" + id + ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isUnearthed() {
|
public final boolean isUnearthed() {
|
||||||
@@ -6273,26 +6244,17 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
view.updateCommander(this);
|
view.updateCommander(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSplitStateToPlayAbility(SpellAbility sa) {
|
public void setSplitStateToPlayAbility(final SpellAbility sa) {
|
||||||
if (!isSplitCard()) { return; } // just in case
|
if (!isSplitCard()) {
|
||||||
|
return; // just in case
|
||||||
|
}
|
||||||
// Split card support
|
// Split card support
|
||||||
for (SpellAbility a : getState(CardStateName.LeftSplit).getNonManaAbilities()) {
|
if (sa.isLeftSplit()) {
|
||||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
|
||||||
setState(CardStateName.LeftSplit, true);
|
setState(CardStateName.LeftSplit, true);
|
||||||
return;
|
} else if (sa.isRightSplit()) {
|
||||||
}
|
|
||||||
}
|
|
||||||
for (SpellAbility a : getState(CardStateName.RightSplit).getNonManaAbilities()) {
|
|
||||||
if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) {
|
|
||||||
setState(CardStateName.RightSplit, true);
|
setState(CardStateName.RightSplit, true);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sa.getHostCard().hasKeyword("Fuse")) { // it's ok that such card won't change its side
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional costs paid
|
// Optional costs paid
|
||||||
private final EnumSet<OptionalCost> costsPaid = EnumSet.noneOf(OptionalCost.class);
|
private final EnumSet<OptionalCost> costsPaid = EnumSet.noneOf(OptionalCost.class);
|
||||||
|
|||||||
@@ -30,82 +30,35 @@ import forge.card.mana.ManaCostParser;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class CardColor {
|
public class CardColor {
|
||||||
private static long timeStamp = 0;
|
|
||||||
public static long getTimestamp() { return CardColor.timeStamp; }
|
|
||||||
static void increaseTimestamp() { CardColor.timeStamp++; }
|
|
||||||
|
|
||||||
// takes care of individual card color, for global color change effects use
|
|
||||||
// AllZone.getGameInfo().getColorChanges()
|
|
||||||
private final byte colorMask;
|
private final byte colorMask;
|
||||||
public final byte getColorMask() { return colorMask; }
|
public final byte getColorMask() {
|
||||||
|
return colorMask;
|
||||||
|
}
|
||||||
|
|
||||||
private final boolean additional;
|
private final boolean additional;
|
||||||
public final boolean isAdditional() {
|
public final boolean isAdditional() {
|
||||||
return this.additional;
|
return this.additional;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long stamp = 0;
|
private final long timestamp;
|
||||||
|
public final long getTimestamp() {
|
||||||
/**
|
return this.timestamp;
|
||||||
* <p>
|
|
||||||
* Getter for the field <code>stamp</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a long.
|
|
||||||
*/
|
|
||||||
public final long getStamp() {
|
|
||||||
return this.stamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
CardColor(final String colors) {
|
||||||
* <p>
|
this(colors, false, 0L);
|
||||||
* Constructor for Card_Color.
|
}
|
||||||
* </p>
|
CardColor(final String colors, final boolean addToColors, final long timestamp) {
|
||||||
*
|
final ManaCost mc = new ManaCost(new ManaCostParser(colors));
|
||||||
* @param mc
|
|
||||||
* a {@link forge.game.mana.ManaCostBeingPaid} object.
|
|
||||||
* @param c
|
|
||||||
* a {@link forge.game.card.Card} object.
|
|
||||||
* @param addToColors
|
|
||||||
* a boolean.
|
|
||||||
* @param baseColor
|
|
||||||
* a boolean.
|
|
||||||
*/
|
|
||||||
CardColor(final String colors, final boolean addToColors) {
|
|
||||||
this.additional = addToColors;
|
|
||||||
ManaCost mc = new ManaCost(new ManaCostParser(colors));
|
|
||||||
this.colorMask = mc.getColorProfile();
|
this.colorMask = mc.getColorProfile();
|
||||||
this.stamp = CardColor.timeStamp;
|
this.additional = addToColors;
|
||||||
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardColor(byte mask) {
|
CardColor(final byte mask) {
|
||||||
this.colorMask = mask;
|
this.colorMask = mask;
|
||||||
this.additional = false;
|
this.additional = false;
|
||||||
this.stamp = 0;
|
this.timestamp = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public CardColor() {
|
|
||||||
this((byte)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* equals.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param cost
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @param c
|
|
||||||
* a {@link forge.game.card.Card} object.
|
|
||||||
* @param addToColors
|
|
||||||
* a boolean.
|
|
||||||
* @param time
|
|
||||||
* a long.
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public final boolean equals(final String cost, final Card c, final boolean addToColors, final long time) {
|
|
||||||
return (addToColors == this.additional) && (this.stamp == time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ColorSet toColorSet() {
|
public final ColorSet toColorSet() {
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public class CardFactory {
|
|||||||
}
|
}
|
||||||
final String finalColors = tmp;
|
final String finalColors = tmp;
|
||||||
|
|
||||||
c.addColor(finalColors, !sourceSA.hasParam("OverwriteColors"), true);
|
c.addColor(finalColors, !sourceSA.hasParam("OverwriteColors"), c.getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
c.clearControllers();
|
c.clearControllers();
|
||||||
@@ -288,7 +288,14 @@ public class CardFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == CardStateName.LeftSplit || state == CardStateName.RightSplit) {
|
if (state == CardStateName.LeftSplit || state == CardStateName.RightSplit) {
|
||||||
CardState original = card.getState(CardStateName.Original);
|
for (final SpellAbility sa : card.getSpellAbilities()) {
|
||||||
|
if (state == CardStateName.LeftSplit) {
|
||||||
|
sa.setLeftSplit();
|
||||||
|
} else {
|
||||||
|
sa.setRightSplit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final CardState original = card.getState(CardStateName.Original);
|
||||||
original.addNonManaAbilities(card.getCurrentState().getNonManaAbilities());
|
original.addNonManaAbilities(card.getCurrentState().getNonManaAbilities());
|
||||||
original.addIntrinsicKeywords(card.getCurrentState().getIntrinsicKeywords()); // Copy 'Fuse' to original side
|
original.addIntrinsicKeywords(card.getCurrentState().getIntrinsicKeywords()); // Copy 'Fuse' to original side
|
||||||
original.getSVars().putAll(card.getCurrentState().getSVars()); // Unfortunately need to copy these to (Effect looks for sVars on execute)
|
original.getSVars().putAll(card.getCurrentState().getSVars()); // Unfortunately need to copy these to (Effect looks for sVars on execute)
|
||||||
@@ -306,7 +313,7 @@ public class CardFactory {
|
|||||||
else if (card.isPlane()) {
|
else if (card.isPlane()) {
|
||||||
buildPlaneAbilities(card);
|
buildPlaneAbilities(card);
|
||||||
}
|
}
|
||||||
CardFactoryUtil.setupKeywordedAbilities(card);
|
CardFactoryUtil.setupKeywordedAbilities(card); // Should happen AFTER setting left/right split abilities to set Fuse ability to both sides
|
||||||
card.getView().updateState(card);
|
card.getView().updateState(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,11 +386,8 @@ public class CardFactory {
|
|||||||
card.setManaCost(combinedManaCost);
|
card.setManaCost(combinedManaCost);
|
||||||
|
|
||||||
// Combined card color
|
// Combined card color
|
||||||
int combinedColor = rules.getMainPart().getColor().getColor() | rules.getOtherPart().getColor().getColor();
|
final byte combinedColor = (byte) (rules.getMainPart().getColor().getColor() | rules.getOtherPart().getColor().getColor());
|
||||||
CardColor combinedCardColor = new CardColor((byte)combinedColor);
|
card.setColor(combinedColor);
|
||||||
ArrayList<CardColor> combinedCardColorArr = new ArrayList<CardColor>();
|
|
||||||
combinedCardColorArr.add(combinedCardColor);
|
|
||||||
card.setColor(combinedCardColorArr);
|
|
||||||
card.setType(new CardType(rules.getType()));
|
card.setType(new CardType(rules.getType()));
|
||||||
|
|
||||||
// Combined text based on Oracle text - might not be necessary, temporarily disabled.
|
// Combined text based on Oracle text - might not be necessary, temporarily disabled.
|
||||||
@@ -411,11 +415,7 @@ public class CardFactory {
|
|||||||
// Super and 'middle' types should use enums.
|
// Super and 'middle' types should use enums.
|
||||||
c.setType(new CardType(face.getType()));
|
c.setType(new CardType(face.getType()));
|
||||||
|
|
||||||
// What a perverted color code we have!
|
c.setColor(face.getColor().getColor());
|
||||||
CardColor col1 = new CardColor(face.getColor().getColor());
|
|
||||||
ArrayList<CardColor> ccc = new ArrayList<CardColor>();
|
|
||||||
ccc.add(col1);
|
|
||||||
c.setColor(ccc);
|
|
||||||
|
|
||||||
if (face.getIntPower() >= 0) {
|
if (face.getIntPower() >= 0) {
|
||||||
c.setBasePower(face.getIntPower());
|
c.setBasePower(face.getIntPower());
|
||||||
@@ -657,7 +657,7 @@ public class CardFactory {
|
|||||||
|
|
||||||
// TODO - most tokens mana cost is 0, this needs to be fixed
|
// TODO - most tokens mana cost is 0, this needs to be fixed
|
||||||
// c.setManaCost(manaCost);
|
// c.setManaCost(manaCost);
|
||||||
c.addColor(manaCost);
|
c.setColor(manaCost);
|
||||||
c.setToken(true);
|
c.setToken(true);
|
||||||
|
|
||||||
for (final String t : types) {
|
for (final String t : types) {
|
||||||
|
|||||||
@@ -17,8 +17,17 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.card;
|
package forge.game.card;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
@@ -34,19 +43,11 @@ import forge.game.trigger.Trigger;
|
|||||||
import forge.util.FCollection;
|
import forge.util.FCollection;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
|
|
||||||
public class CardState {
|
public class CardState {
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private CardType type = new CardType();
|
private CardType type = new CardType();
|
||||||
private ManaCost manaCost = ManaCost.NO_COST;
|
private ManaCost manaCost = ManaCost.NO_COST;
|
||||||
private List<CardColor> cardColor = new ArrayList<CardColor>();
|
private final SortedMap<Long, CardColor> cardColor = Maps.newTreeMap();
|
||||||
private int basePower = 0;
|
private int basePower = 0;
|
||||||
private int baseToughness = 0;
|
private int baseToughness = 0;
|
||||||
private List<String> intrinsicKeywords = new ArrayList<String>();
|
private List<String> intrinsicKeywords = new ArrayList<String>();
|
||||||
@@ -117,27 +118,49 @@ public class CardState {
|
|||||||
view.updateManaCost(this);
|
view.updateManaCost(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<CardColor> getCardColor() {
|
public final void addColor(final CardColor color) {
|
||||||
return cardColor;
|
cardColor.put(color.getTimestamp(), color);
|
||||||
|
getView().updateColors(this);
|
||||||
}
|
}
|
||||||
public final void setCardColor(final Iterable<CardColor> cardColor0) {
|
|
||||||
cardColor = Lists.newArrayList(cardColor0);
|
public final void addColor(final String s, final boolean addToColors, final long timestamp) {
|
||||||
|
addColor(new CardColor(s, addToColors, timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void removeColor(final long timestampIn) {
|
||||||
|
final CardColor removeCol = cardColor.remove(timestampIn);
|
||||||
|
|
||||||
|
if (removeCol != null) {
|
||||||
|
getView().updateColors(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setColor(final CardColor color) {
|
||||||
|
setColor(ImmutableMap.of(color.getTimestamp(), color));
|
||||||
|
}
|
||||||
|
private final void setColor(final Map<Long, CardColor> cardColor0) {
|
||||||
|
cardColor.clear();
|
||||||
|
cardColor.putAll(cardColor0);
|
||||||
view.updateColors(this);
|
view.updateColors(this);
|
||||||
}
|
}
|
||||||
public final void resetCardColor() {
|
public final void resetCardColor() {
|
||||||
if (cardColor.isEmpty()) { return; }
|
if (cardColor.isEmpty()) {
|
||||||
|
return;
|
||||||
cardColor = Lists.newArrayList(cardColor.subList(0, 1));
|
}
|
||||||
|
final Long firstKey = cardColor.firstKey();
|
||||||
|
final CardColor first = cardColor.get(firstKey);
|
||||||
|
cardColor.clear();
|
||||||
|
cardColor.put(firstKey, first);
|
||||||
view.updateColors(this);
|
view.updateColors(this);
|
||||||
}
|
}
|
||||||
public final ColorSet determineColor() {
|
public final ColorSet determineColor() {
|
||||||
final List<CardColor> colorList = getCardColor();
|
final Iterable<CardColor> colorList = cardColor.values();
|
||||||
byte colors = 0;
|
byte colors = 0;
|
||||||
for (int i = colorList.size() - 1;i >= 0;i--) {
|
for (final CardColor cc : colorList) {
|
||||||
final CardColor cc = colorList.get(i);
|
if (cc.isAdditional()) {
|
||||||
colors |= cc.getColorMask();
|
colors |= cc.getColorMask();
|
||||||
if (!cc.isAdditional()) {
|
} else {
|
||||||
return ColorSet.fromMask(colors);
|
colors = cc.getColorMask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ColorSet.fromMask(colors);
|
return ColorSet.fromMask(colors);
|
||||||
@@ -366,7 +389,7 @@ public class CardState {
|
|||||||
setName(source.getName());
|
setName(source.getName());
|
||||||
setType(source.type);
|
setType(source.type);
|
||||||
setManaCost(source.getManaCost());
|
setManaCost(source.getManaCost());
|
||||||
setCardColor(source.getCardColor());
|
setColor(source.cardColor);
|
||||||
setBasePower(source.getBasePower());
|
setBasePower(source.getBasePower());
|
||||||
setBaseToughness(source.getBaseToughness());
|
setBaseToughness(source.getBaseToughness());
|
||||||
intrinsicKeywords = new ArrayList<String>(source.intrinsicKeywords);
|
intrinsicKeywords = new ArrayList<String>(source.intrinsicKeywords);
|
||||||
|
|||||||
@@ -240,10 +240,7 @@ public final class CardUtil {
|
|||||||
newCopy.setCounters(in.getCounters());
|
newCopy.setCounters(in.getCounters());
|
||||||
newCopy.setExtrinsicKeyword(in.getExtrinsicKeyword());
|
newCopy.setExtrinsicKeyword(in.getExtrinsicKeyword());
|
||||||
|
|
||||||
// Determine the color for LKI copy, not just getColor
|
newCopy.setColor(in.determineColor().getColor());
|
||||||
ArrayList<CardColor> currentColor = new ArrayList<CardColor>();
|
|
||||||
currentColor.add(new CardColor(in.determineColor().getColor()));
|
|
||||||
newCopy.setColor(currentColor);
|
|
||||||
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
|
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
|
||||||
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn());
|
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn());
|
||||||
newCopy.setEnchanting(in.getEnchanting());
|
newCopy.setEnchanting(in.getEnchanting());
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import forge.item.IPaperCard;
|
|||||||
import forge.trackable.TrackableCollection;
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.trackable.TrackableObject;
|
import forge.trackable.TrackableObject;
|
||||||
import forge.trackable.TrackableProperty;
|
import forge.trackable.TrackableProperty;
|
||||||
|
import forge.trackable.Tracker;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
public class CardView extends GameEntityView {
|
public class CardView extends GameEntityView {
|
||||||
@@ -68,20 +69,20 @@ public class CardView extends GameEntityView {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardView(int id0) {
|
public CardView(final int id0, final Tracker tracker) {
|
||||||
super(id0);
|
super(id0, tracker);
|
||||||
set(TrackableProperty.CurrentState, new CardStateView(id0, CardStateName.Original));
|
set(TrackableProperty.CurrentState, new CardStateView(id0, CardStateName.Original, tracker));
|
||||||
}
|
}
|
||||||
public CardView(int id0, String name0) {
|
public CardView(final int id0, final Tracker tracker, final String name0) {
|
||||||
this(id0);
|
this(id0, tracker);
|
||||||
getCurrentState().setName(name0);
|
getCurrentState().setName(name0);
|
||||||
set(TrackableProperty.Name, name0);
|
set(TrackableProperty.Name, name0);
|
||||||
set(TrackableProperty.ChangedColorWords, new HashMap<String, String>());
|
set(TrackableProperty.ChangedColorWords, new HashMap<String, String>());
|
||||||
set(TrackableProperty.ChangedTypes, new HashMap<String, String>());
|
set(TrackableProperty.ChangedTypes, new HashMap<String, String>());
|
||||||
set(TrackableProperty.Sickness, true);
|
set(TrackableProperty.Sickness, true);
|
||||||
}
|
}
|
||||||
public CardView(int id0, String name0, PlayerView ownerAndController, String imageKey) {
|
public CardView(final int id0, final Tracker tracker, final String name0, final PlayerView ownerAndController, final String imageKey) {
|
||||||
this(id0, name0);
|
this(id0, tracker, name0);
|
||||||
set(TrackableProperty.Owner, ownerAndController);
|
set(TrackableProperty.Owner, ownerAndController);
|
||||||
set(TrackableProperty.Controller, ownerAndController);
|
set(TrackableProperty.Controller, ownerAndController);
|
||||||
set(TrackableProperty.ImageKey, imageKey);
|
set(TrackableProperty.ImageKey, imageKey);
|
||||||
@@ -632,8 +633,8 @@ public class CardView extends GameEntityView {
|
|||||||
public CardStateView getAlternateState() {
|
public CardStateView getAlternateState() {
|
||||||
return get(TrackableProperty.AlternateState);
|
return get(TrackableProperty.AlternateState);
|
||||||
}
|
}
|
||||||
CardStateView createAlternateState(CardStateName state0) {
|
CardStateView createAlternateState(final CardStateName state0) {
|
||||||
return new CardStateView(getId(), state0);
|
return new CardStateView(getId(), state0, tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardStateView getState(final boolean alternate0) {
|
public CardStateView getState(final boolean alternate0) {
|
||||||
@@ -716,8 +717,8 @@ public class CardView extends GameEntityView {
|
|||||||
public class CardStateView extends TrackableObject {
|
public class CardStateView extends TrackableObject {
|
||||||
private final CardStateName state;
|
private final CardStateName state;
|
||||||
|
|
||||||
public CardStateView(int id0, CardStateName state0) {
|
public CardStateView(final int id0, final CardStateName state0, final Tracker tracker) {
|
||||||
super(id0);
|
super(id0, tracker);
|
||||||
state = state0;
|
state = state0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,13 @@ import forge.game.GameEntityView;
|
|||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.trackable.TrackableObject;
|
import forge.trackable.TrackableObject;
|
||||||
import forge.trackable.TrackableProperty;
|
import forge.trackable.TrackableProperty;
|
||||||
|
import forge.trackable.Tracker;
|
||||||
import forge.util.FCollection;
|
import forge.util.FCollection;
|
||||||
|
|
||||||
|
|
||||||
public class CombatView extends TrackableObject {
|
public class CombatView extends TrackableObject {
|
||||||
public CombatView() {
|
public CombatView(final Tracker tracker) {
|
||||||
super(-1); //ID not needed
|
super(-1, tracker); //ID not needed
|
||||||
set(TrackableProperty.AttackersWithDefenders, new HashMap<CardView, GameEntityView>());
|
set(TrackableProperty.AttackersWithDefenders, new HashMap<CardView, GameEntityView>());
|
||||||
set(TrackableProperty.AttackersWithBlockers, new HashMap<CardView, FCollection<CardView>>());
|
set(TrackableProperty.AttackersWithBlockers, new HashMap<CardView, FCollection<CardView>>());
|
||||||
set(TrackableProperty.BandsWithDefenders, new HashMap<FCollection<CardView>, GameEntityView>());
|
set(TrackableProperty.BandsWithDefenders, new HashMap<FCollection<CardView>, GameEntityView>());
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
zones.put(z, toPut);
|
zones.put(z, toPut);
|
||||||
}
|
}
|
||||||
|
|
||||||
view = new PlayerView(id0);
|
view = new PlayerView(id0, game.getTracker());
|
||||||
view.updateMaxHandSize(this);
|
view.updateMaxHandSize(this);
|
||||||
view.updateKeywords(this);
|
view.updateKeywords(this);
|
||||||
setName(chooseName(name0));
|
setName(chooseName(name0));
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import forge.game.zone.PlayerZone;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.trackable.TrackableCollection;
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.trackable.TrackableProperty;
|
import forge.trackable.TrackableProperty;
|
||||||
|
import forge.trackable.Tracker;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
|
|
||||||
@@ -35,8 +36,8 @@ public class PlayerView extends GameEntityView {
|
|||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerView(int id0) {
|
public PlayerView(final int id0, final Tracker tracker) {
|
||||||
super(id0);
|
super(id0, tracker);
|
||||||
|
|
||||||
set(TrackableProperty.Mana, Maps.newHashMapWithExpectedSize(MagicColor.NUMBER_OR_COLORS + 1));
|
set(TrackableProperty.Mana, Maps.newHashMapWithExpectedSize(MagicColor.NUMBER_OR_COLORS + 1));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
private boolean morphup = false;
|
private boolean morphup = false;
|
||||||
private boolean cumulativeupkeep = false;
|
private boolean cumulativeupkeep = false;
|
||||||
private boolean outlast = false;
|
private boolean outlast = false;
|
||||||
|
private SplitSide splitSide = null;
|
||||||
|
enum SplitSide { LEFT, RIGHT };
|
||||||
private int totalManaSpent = 0;
|
private int totalManaSpent = 0;
|
||||||
|
|
||||||
/** The pay costs. */
|
/** The pay costs. */
|
||||||
@@ -545,6 +547,22 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
outlast = outlast0;
|
outlast = outlast0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLeftSplit() {
|
||||||
|
return splitSide == SplitSide.LEFT;
|
||||||
|
}
|
||||||
|
public boolean isRightSplit() {
|
||||||
|
return splitSide == SplitSide.RIGHT;
|
||||||
|
}
|
||||||
|
public void setNoSplit() {
|
||||||
|
splitSide = null;
|
||||||
|
}
|
||||||
|
public void setLeftSplit() {
|
||||||
|
splitSide = SplitSide.LEFT;
|
||||||
|
}
|
||||||
|
public void setRightSplit() {
|
||||||
|
splitSide = SplitSide.RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
public SpellAbility copy() {
|
public SpellAbility copy() {
|
||||||
SpellAbility clone = null;
|
SpellAbility clone = null;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ public class SpellAbilityView extends TrackableObject {
|
|||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellAbilityView(SpellAbility sa) {
|
SpellAbilityView(final SpellAbility sa) {
|
||||||
super(sa.getId());
|
super(sa.getId(), sa.getHostCard() == null || sa.getHostCard().getGame() == null ? null : sa.getHostCard().getGame().getTracker());
|
||||||
updateHostCard(sa);
|
updateHostCard(sa);
|
||||||
updateDescription(sa);
|
updateDescription(sa);
|
||||||
updatePromptIfOnlyPossibleAbility(sa);
|
updatePromptIfOnlyPossibleAbility(sa);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class StackItemView extends TrackableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StackItemView(SpellAbilityStackInstance si) {
|
public StackItemView(SpellAbilityStackInstance si) {
|
||||||
super(si.getId());
|
super(si.getId(), si.getSourceCard().getGame().getTracker());
|
||||||
updateKey(si);
|
updateKey(si);
|
||||||
updateSourceTrigger(si);
|
updateSourceTrigger(si);
|
||||||
updateText(si);
|
updateText(si);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import forge.game.CardTraitBase;
|
|||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
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.CardCollectionView;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -30,20 +32,22 @@ import forge.game.zone.ZoneType;
|
|||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class StaticAbility.
|
* The Class StaticAbility.
|
||||||
*/
|
*/
|
||||||
public class StaticAbility extends CardTraitBase {
|
public class StaticAbility extends CardTraitBase {
|
||||||
|
|
||||||
private int layer = 0;
|
private final Set<StaticAbilityLayer> layers;
|
||||||
private List<Card> ignoreEffectCards = new ArrayList<Card>();
|
private CardCollectionView ignoreEffectCards = new CardCollection();
|
||||||
private List<Player> ignoreEffectPlayers = new ArrayList<Player>();
|
private final List<Player> ignoreEffectPlayers = new ArrayList<Player>();
|
||||||
|
|
||||||
// *******************************************************
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -56,8 +60,8 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @return a {@link java.util.HashMap} object.
|
* @return a {@link java.util.HashMap} object.
|
||||||
*/
|
*/
|
||||||
private static HashMap<String, String> parseParams(final String abString, final Card hostCard) {
|
private static Map<String, String> parseParams(final String abString, final Card hostCard) {
|
||||||
final HashMap<String, String> mapParameters = new HashMap<String, String>();
|
final Map<String, String> mapParameters = Maps.newHashMap();
|
||||||
|
|
||||||
if (!(abString.length() > 0)) {
|
if (!(abString.length() > 0)) {
|
||||||
throw new RuntimeException("StaticEffectFactory : getAbility -- abString too short in "
|
throw new RuntimeException("StaticEffectFactory : getAbility -- abString too short in "
|
||||||
@@ -94,58 +98,63 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
return mapParameters;
|
return mapParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In which layer should the ability be applied (for continuous effects
|
|
||||||
// only)
|
|
||||||
/**
|
/**
|
||||||
* Gets the layer.
|
* Gets the {@link Set} of {@link StaticAbilityLayer}s in which this
|
||||||
|
* {@link StaticAbility} is to be applied.
|
||||||
*
|
*
|
||||||
* @return the layer
|
* @return the applicable layers.
|
||||||
*/
|
*/
|
||||||
public final int generateLayer() {
|
private final Set<StaticAbilityLayer> generateLayer() {
|
||||||
|
|
||||||
if (!this.mapParams.get("Mode").equals("Continuous")) {
|
if (!this.mapParams.get("Mode").equals("Continuous")) {
|
||||||
return 0;
|
return EnumSet.noneOf(StaticAbilityLayer.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Set<StaticAbilityLayer> layers = EnumSet.noneOf(StaticAbilityLayer.class);
|
||||||
if (this.mapParams.containsKey("GainControl")) {
|
if (this.mapParams.containsKey("GainControl")) {
|
||||||
return 2;
|
layers.add(StaticAbilityLayer.CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("ChangeColorWordsTo")) {
|
if (this.mapParams.containsKey("ChangeColorWordsTo")) {
|
||||||
return 3;
|
layers.add(StaticAbilityLayer.TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("AddType") || this.mapParams.containsKey("RemoveType")
|
if (this.mapParams.containsKey("AddType") || this.mapParams.containsKey("RemoveType")
|
||||||
|| this.mapParams.containsKey("RemoveCardTypes") || this.mapParams.containsKey("RemoveSubTypes")
|
|| this.mapParams.containsKey("RemoveCardTypes") || this.mapParams.containsKey("RemoveSubTypes")
|
||||||
|| this.mapParams.containsKey("RemoveSuperTypes") || this.mapParams.containsKey("RemoveCreatureTypes")) {
|
|| this.mapParams.containsKey("RemoveSuperTypes") || this.mapParams.containsKey("RemoveCreatureTypes")) {
|
||||||
return 4;
|
layers.add(StaticAbilityLayer.TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("AddColor") || this.mapParams.containsKey("RemoveColor")
|
if (this.mapParams.containsKey("AddColor") || this.mapParams.containsKey("RemoveColor")
|
||||||
|| this.mapParams.containsKey("SetColor")) {
|
|| this.mapParams.containsKey("SetColor")) {
|
||||||
return 5;
|
layers.add(StaticAbilityLayer.COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("RemoveAllAbilities") || this.mapParams.containsKey("GainsAbilitiesOf")) {
|
if (this.mapParams.containsKey("RemoveAllAbilities") || this.mapParams.containsKey("GainsAbilitiesOf")) {
|
||||||
return 6; // Layer 6
|
layers.add(StaticAbilityLayer.ABILITIES1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("AddKeyword") || this.mapParams.containsKey("AddAbility")
|
if (this.mapParams.containsKey("AddKeyword") || this.mapParams.containsKey("AddAbility")
|
||||||
|| this.mapParams.containsKey("AddTrigger") || this.mapParams.containsKey("RemoveTriggers")
|
|| this.mapParams.containsKey("AddTrigger") || this.mapParams.containsKey("RemoveTriggers")
|
||||||
|| this.mapParams.containsKey("RemoveKeyword") || this.mapParams.containsKey("AddReplacementEffects")) {
|
|| this.mapParams.containsKey("RemoveKeyword") || this.mapParams.containsKey("AddReplacementEffects")) {
|
||||||
return 7; // Layer 6 (dependent)
|
layers.add(StaticAbilityLayer.ABILITIES2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("CharacteristicDefining")) {
|
if (this.mapParams.containsKey("CharacteristicDefining")) {
|
||||||
return 8; // Layer 7a
|
layers.add(StaticAbilityLayer.CHARACTERISTIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mapParams.containsKey("AddPower") || this.mapParams.containsKey("AddToughness")
|
if (this.mapParams.containsKey("SetPower") || this.mapParams.containsKey("SetToughness")) {
|
||||||
|| this.mapParams.containsKey("SetPower") || this.mapParams.containsKey("SetToughness")) {
|
layers.add(StaticAbilityLayer.SETPT);
|
||||||
return 9; // This is the collection of 7b and 7c
|
}
|
||||||
|
if (this.mapParams.containsKey("AddPower") || this.mapParams.containsKey("AddToughness")) {
|
||||||
|
layers.add(StaticAbilityLayer.MODIFYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 10; // rules change
|
if (layers.isEmpty()) {
|
||||||
|
return EnumSet.of(StaticAbilityLayer.RULES);
|
||||||
|
}
|
||||||
|
|
||||||
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,11 +183,7 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
* the host
|
* the host
|
||||||
*/
|
*/
|
||||||
public StaticAbility(final String params, final Card host) {
|
public StaticAbility(final String params, final Card host) {
|
||||||
final Map<String, String> parsedParams = parseParams(params, host);
|
this(parseParams(params, host), host);
|
||||||
this.originalMapParams.putAll(parsedParams);
|
|
||||||
this.mapParams.putAll(parsedParams);
|
|
||||||
this.hostCard = host;
|
|
||||||
this.layer = this.generateLayer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,37 +194,49 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
* @param host
|
* @param host
|
||||||
* the host
|
* the host
|
||||||
*/
|
*/
|
||||||
public StaticAbility(final Map<String, String> params, final Card host) {
|
private StaticAbility(final Map<String, String> params, final Card host) {
|
||||||
this.originalMapParams.putAll(params);
|
this.originalMapParams.putAll(params);
|
||||||
this.mapParams.putAll(params);
|
this.mapParams.putAll(params);
|
||||||
this.layer = this.generateLayer();
|
this.layers = this.generateLayer();
|
||||||
this.hostCard = host;
|
this.hostCard = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply the ability if it has the right mode
|
public final CardCollectionView applyContinuousAbility(final StaticAbilityLayer layer) {
|
||||||
|
if (!shouldApplyContinuousAbility(layer, false)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return StaticAbilityContinuous.applyContinuousAbility(this, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final CardCollectionView applyContinuousAbility(final StaticAbilityLayer layer, final CardCollectionView affected) {
|
||||||
|
if (!shouldApplyContinuousAbility(layer, true)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return StaticAbilityContinuous.applyContinuousAbility(this, affected, layer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply ability.
|
* Check whether a continuous ability should be applied.
|
||||||
*
|
*
|
||||||
* @param mode
|
* @param layer
|
||||||
* the mode
|
* the {@link StaticAbilityLayer} under investigation.
|
||||||
* @return
|
* @param ignoreTempSuppression
|
||||||
|
* whether to ignore temporary suppression of this ability, to be
|
||||||
|
* used when this ability has already begun applying in another
|
||||||
|
* layer and has since been removed from its host card by another
|
||||||
|
* effect (see rule 613.5).
|
||||||
|
* @return {@code true} if and only if this is a continuous ability that
|
||||||
|
* affects the specified layer, it's not suppressed, and its
|
||||||
|
* conditions are fulfilled.
|
||||||
*/
|
*/
|
||||||
public final List<Card> applyAbility(final String mode) {
|
private boolean shouldApplyContinuousAbility(final StaticAbilityLayer layer, final boolean ignoreTempSuppression) {
|
||||||
|
final boolean isSuppressed;
|
||||||
// don't apply the ability if it hasn't got the right mode
|
if (ignoreTempSuppression) {
|
||||||
if (!this.mapParams.get("Mode").equals(mode)) {
|
isSuppressed = this.isNonTempSuppressed();
|
||||||
return null;
|
} else {
|
||||||
|
isSuppressed = this.isSuppressed();
|
||||||
}
|
}
|
||||||
|
return mapParams.get("Mode").equals("Continuous") && layers.contains(layer) && !isSuppressed && this.checkConditions();
|
||||||
if (this.isSuppressed() || !this.checkConditions()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode.equals("Continuous")) {
|
|
||||||
return StaticAbilityContinuous.applyContinuousAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply the ability if it has the right mode
|
// apply the ability if it has the right mode
|
||||||
@@ -557,15 +574,15 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
/**
|
/**
|
||||||
* @return the ignoreEffectCards
|
* @return the ignoreEffectCards
|
||||||
*/
|
*/
|
||||||
public List<Card> getIgnoreEffectCards() {
|
public CardCollectionView getIgnoreEffectCards() {
|
||||||
return ignoreEffectCards;
|
return ignoreEffectCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param c the ignoreEffectCards to set
|
* @param c the ignoreEffectCards to set
|
||||||
*/
|
*/
|
||||||
public void setIgnoreEffectCards(List<Card> cards) {
|
public void setIgnoreEffectCards(final CardCollectionView cards) {
|
||||||
this.ignoreEffectCards = cards;
|
ignoreEffectCards = cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -578,27 +595,20 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
/**
|
/**
|
||||||
* @param p the ignoreEffectPlayers to add
|
* @param p the ignoreEffectPlayers to add
|
||||||
*/
|
*/
|
||||||
public void addIgnoreEffectPlayers(Player p) {
|
public void addIgnoreEffectPlayers(final Player p) {
|
||||||
this.ignoreEffectPlayers.add(p);
|
ignoreEffectPlayers.add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearIgnoreEffects() {
|
public void clearIgnoreEffects() {
|
||||||
this.ignoreEffectPlayers.clear();
|
ignoreEffectPlayers.clear();
|
||||||
this.ignoreEffectCards.clear();
|
ignoreEffectCards = new CardCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the layer
|
* @return the layer
|
||||||
*/
|
*/
|
||||||
public int getLayer() {
|
public Set<StaticAbilityLayer> getLayers() {
|
||||||
return layer;
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
} // end class StaticAbility
|
||||||
* @param layer the layer to set
|
|
||||||
*/
|
|
||||||
public void setLayer(int layer) {
|
|
||||||
this.layer = layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end class StaticEffectFactory
|
|
||||||
|
|||||||
@@ -17,14 +17,24 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.staticability;
|
package forge.game.staticability;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
import forge.GameCommand;
|
import forge.GameCommand;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.game.*;
|
import forge.game.Game;
|
||||||
|
import forge.game.GlobalRuleChange;
|
||||||
|
import forge.game.StaticEffect;
|
||||||
|
import forge.game.StaticEffects;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
@@ -45,43 +55,59 @@ import forge.game.trigger.Trigger;
|
|||||||
import forge.game.trigger.TriggerHandler;
|
import forge.game.trigger.TriggerHandler;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class StaticAbility_Continuous.
|
* The Class StaticAbility_Continuous.
|
||||||
*/
|
*/
|
||||||
public class StaticAbilityContinuous {
|
public final class StaticAbilityContinuous {
|
||||||
|
|
||||||
public static List<Card> applyContinuousAbility(final StaticAbility stAb) {
|
// Private constructor to prevent instantiation
|
||||||
final List<Card> affectedCards = StaticAbilityContinuous.getAffectedCards(stAb);
|
private StaticAbilityContinuous() {
|
||||||
return applyContinuousAbility(stAb, affectedCards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Apply the effects of a static ability that apply in a particular layer.
|
||||||
* TODO Write javadoc for this method.
|
* The cards to which the effects are applied are dynamically determined.
|
||||||
*
|
*
|
||||||
* @param stAb
|
* @param stAb
|
||||||
* a StaticAbility
|
* a {@link StaticAbility}.
|
||||||
* @return
|
* @param layer
|
||||||
*
|
* the {@link StaticAbilityLayer} of effects to apply.
|
||||||
|
* @return a {@link CardCollectionView} of cards that have been affected.
|
||||||
|
* @see #getAffectedCards(StaticAbility)
|
||||||
|
* @see #applyContinuousAbility(StaticAbility, CardCollectionView,
|
||||||
|
* StaticAbilityLayer)
|
||||||
*/
|
*/
|
||||||
public static List<Card> applyContinuousAbility(final StaticAbility stAb, List<Card> affectedCards) {
|
public static CardCollectionView applyContinuousAbility(final StaticAbility stAb, final StaticAbilityLayer layer) {
|
||||||
|
final CardCollectionView affectedCards = getAffectedCards(stAb);
|
||||||
|
return applyContinuousAbility(stAb, affectedCards, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the effects of a static ability that apply in a particular layer to
|
||||||
|
* a predefined set of cards.
|
||||||
|
*
|
||||||
|
* @param stAb
|
||||||
|
* a {@link StaticAbility}.
|
||||||
|
* @param affectedCards
|
||||||
|
* a {@link CardCollectionView} of cards that are to be affected.
|
||||||
|
* @param layer
|
||||||
|
* the {@link StaticAbilityLayer} of effects to apply.
|
||||||
|
* @return a {@link CardCollectionView} of cards that have been affected,
|
||||||
|
* identical to {@code affectedCards}.
|
||||||
|
*/
|
||||||
|
public static CardCollectionView applyContinuousAbility(final StaticAbility stAb, final CardCollectionView affectedCards, final StaticAbilityLayer layer) {
|
||||||
final Map<String, String> params = stAb.getMapParams();
|
final Map<String, String> params = stAb.getMapParams();
|
||||||
final Card hostCard = stAb.getHostCard();
|
final Card hostCard = stAb.getHostCard();
|
||||||
final Player controller = hostCard.getController();
|
final Player controller = hostCard.getController();
|
||||||
|
|
||||||
final StaticEffect se = new StaticEffect(hostCard);
|
|
||||||
final ArrayList<Player> affectedPlayers = StaticAbilityContinuous.getAffectedPlayers(stAb);
|
final ArrayList<Player> affectedPlayers = StaticAbilityContinuous.getAffectedPlayers(stAb);
|
||||||
final Game game = hostCard.getGame();
|
final Game game = hostCard.getGame();
|
||||||
|
|
||||||
|
final StaticEffect se = game.getStaticEffects().getStaticEffect(stAb);
|
||||||
se.setAffectedCards(affectedCards);
|
se.setAffectedCards(affectedCards);
|
||||||
se.setAffectedPlayers(affectedPlayers);
|
se.setAffectedPlayers(affectedPlayers);
|
||||||
se.setParams(params);
|
se.setParams(params);
|
||||||
se.setTimestamp(hostCard.getTimestamp());
|
se.setTimestamp(hostCard.getTimestamp());
|
||||||
game.getStaticEffects().addStaticEffect(se);
|
|
||||||
|
|
||||||
String changeColorWordsTo = null;
|
String changeColorWordsTo = null;
|
||||||
|
|
||||||
@@ -116,26 +142,26 @@ public class StaticAbilityContinuous {
|
|||||||
boolean controllerMayPlay = false, mayPlayWithoutManaCost = false, mayPlayIgnoreColor = false;
|
boolean controllerMayPlay = false, mayPlayWithoutManaCost = false, mayPlayIgnoreColor = false;
|
||||||
|
|
||||||
//Global rules changes
|
//Global rules changes
|
||||||
if (params.containsKey("GlobalRule")) {
|
if (layer == StaticAbilityLayer.RULES && params.containsKey("GlobalRule")) {
|
||||||
final StaticEffects effects = game.getStaticEffects();
|
final StaticEffects effects = game.getStaticEffects();
|
||||||
effects.setGlobalRuleChange(GlobalRuleChange.fromString(params.get("GlobalRule")));
|
effects.setGlobalRuleChange(GlobalRuleChange.fromString(params.get("GlobalRule")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("ChangeColorWordsTo")) {
|
if (layer == StaticAbilityLayer.TEXT && params.containsKey("ChangeColorWordsTo")) {
|
||||||
changeColorWordsTo = params.get("ChangeColorWordsTo");
|
changeColorWordsTo = params.get("ChangeColorWordsTo");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("SetPower")) {
|
if (layer == StaticAbilityLayer.SETPT &¶ms.containsKey("SetPower")) {
|
||||||
setP = params.get("SetPower");
|
setP = params.get("SetPower");
|
||||||
setPower = AbilityUtils.calculateAmount(hostCard, setP, stAb);
|
setPower = AbilityUtils.calculateAmount(hostCard, setP, stAb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("SetToughness")) {
|
if (layer == StaticAbilityLayer.SETPT && params.containsKey("SetToughness")) {
|
||||||
setT = params.get("SetToughness");
|
setT = params.get("SetToughness");
|
||||||
setToughness = AbilityUtils.calculateAmount(hostCard, setT, stAb);
|
setToughness = AbilityUtils.calculateAmount(hostCard, setT, stAb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddPower")) {
|
if (layer == StaticAbilityLayer.MODIFYPT && params.containsKey("AddPower")) {
|
||||||
addP = params.get("AddPower");
|
addP = params.get("AddPower");
|
||||||
powerBonus = AbilityUtils.calculateAmount(hostCard, addP, stAb);
|
powerBonus = AbilityUtils.calculateAmount(hostCard, addP, stAb);
|
||||||
if (!StringUtils.isNumeric(addP) && !addP.equals("AffectedX")) {
|
if (!StringUtils.isNumeric(addP) && !addP.equals("AffectedX")) {
|
||||||
@@ -143,7 +169,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddToughness")) {
|
if (layer == StaticAbilityLayer.MODIFYPT && params.containsKey("AddToughness")) {
|
||||||
addT = params.get("AddToughness");
|
addT = params.get("AddToughness");
|
||||||
toughnessBonus = AbilityUtils.calculateAmount(hostCard, addT, stAb);
|
toughnessBonus = AbilityUtils.calculateAmount(hostCard, addT, stAb);
|
||||||
if (!StringUtils.isNumeric(addT) && !addT.equals("AffectedX")) {
|
if (!StringUtils.isNumeric(addT) && !addT.equals("AffectedX")) {
|
||||||
@@ -151,8 +177,8 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("KeywordMultiplier")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("KeywordMultiplier")) {
|
||||||
String multiplier = params.get("KeywordMultiplier");
|
final String multiplier = params.get("KeywordMultiplier");
|
||||||
if (multiplier.equals("X")) {
|
if (multiplier.equals("X")) {
|
||||||
se.setXValue(AbilityUtils.calculateAmount(hostCard, "X", stAb));
|
se.setXValue(AbilityUtils.calculateAmount(hostCard, "X", stAb));
|
||||||
} else {
|
} else {
|
||||||
@@ -160,7 +186,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddKeyword")) {
|
||||||
addKeywords = params.get("AddKeyword").split(" & ");
|
addKeywords = params.get("AddKeyword").split(" & ");
|
||||||
final Iterable<String> chosencolors = hostCard.getChosenColors();
|
final Iterable<String> chosencolors = hostCard.getChosenColors();
|
||||||
for (final String color : chosencolors) {
|
for (final String color : chosencolors) {
|
||||||
@@ -187,19 +213,19 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddHiddenKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddHiddenKeyword")) {
|
||||||
addHiddenKeywords = params.get("AddHiddenKeyword").split(" & ");
|
addHiddenKeywords = params.get("AddHiddenKeyword").split(" & ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("RemoveKeyword")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("RemoveKeyword")) {
|
||||||
removeKeywords = params.get("RemoveKeyword").split(" & ");
|
removeKeywords = params.get("RemoveKeyword").split(" & ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("RemoveAllAbilities")) {
|
if (layer == StaticAbilityLayer.ABILITIES1 && params.containsKey("RemoveAllAbilities")) {
|
||||||
removeAllAbilities = true;
|
removeAllAbilities = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddAbility")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddAbility")) {
|
||||||
final String[] sVars = params.get("AddAbility").split(" & ");
|
final String[] sVars = params.get("AddAbility").split(" & ");
|
||||||
for (int i = 0; i < sVars.length; i++) {
|
for (int i = 0; i < sVars.length; i++) {
|
||||||
sVars[i] = hostCard.getSVar(sVars[i]);
|
sVars[i] = hostCard.getSVar(sVars[i]);
|
||||||
@@ -207,7 +233,7 @@ public class StaticAbilityContinuous {
|
|||||||
addAbilities = sVars;
|
addAbilities = sVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddReplacementEffects")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddReplacementEffects")) {
|
||||||
final String[] sVars = params.get("AddReplacementEffects").split(" & ");
|
final String[] sVars = params.get("AddReplacementEffects").split(" & ");
|
||||||
for (int i = 0; i < sVars.length; i++) {
|
for (int i = 0; i < sVars.length; i++) {
|
||||||
sVars[i] = hostCard.getSVar(sVars[i]);
|
sVars[i] = hostCard.getSVar(sVars[i]);
|
||||||
@@ -215,11 +241,11 @@ public class StaticAbilityContinuous {
|
|||||||
addReplacements = sVars;
|
addReplacements = sVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddSVar")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("AddSVar")) {
|
||||||
addSVars = params.get("AddSVar").split(" & ");
|
addSVars = params.get("AddSVar").split(" & ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("AddType")) {
|
if (layer == StaticAbilityLayer.TYPE && params.containsKey("AddType")) {
|
||||||
addTypes = params.get("AddType").split(" & ");
|
addTypes = params.get("AddType").split(" & ");
|
||||||
if (addTypes[0].equals("ChosenType")) {
|
if (addTypes[0].equals("ChosenType")) {
|
||||||
final String chosenType = hostCard.getChosenType();
|
final String chosenType = hostCard.getChosenType();
|
||||||
@@ -233,7 +259,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("RemoveType")) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && params.containsKey("RemoveType")) {
|
||||||
removeTypes = params.get("RemoveType").split(" & ");
|
removeTypes = params.get("RemoveType").split(" & ");
|
||||||
if (removeTypes[0].equals("ChosenType")) {
|
if (removeTypes[0].equals("ChosenType")) {
|
||||||
final String chosenType = hostCard.getChosenType();
|
final String chosenType = hostCard.getChosenType();
|
||||||
@@ -242,6 +268,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layer == StaticAbilityLayer.TYPE) {
|
||||||
if (params.containsKey("RemoveSuperTypes")) {
|
if (params.containsKey("RemoveSuperTypes")) {
|
||||||
removeSuperTypes = true;
|
removeSuperTypes = true;
|
||||||
}
|
}
|
||||||
@@ -257,7 +284,9 @@ public class StaticAbilityContinuous {
|
|||||||
if (params.containsKey("RemoveCreatureTypes")) {
|
if (params.containsKey("RemoveCreatureTypes")) {
|
||||||
removeCreatureTypes = true;
|
removeCreatureTypes = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer == StaticAbilityLayer.COLOR) {
|
||||||
if (params.containsKey("AddColor")) {
|
if (params.containsKey("AddColor")) {
|
||||||
final String colors = params.get("AddColor");
|
final String colors = params.get("AddColor");
|
||||||
if (colors.equals("ChosenColor")) {
|
if (colors.equals("ChosenColor")) {
|
||||||
@@ -278,7 +307,9 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
se.setOverwriteColors(true);
|
se.setOverwriteColors(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer == StaticAbilityLayer.ABILITIES2) {
|
||||||
if (params.containsKey("AddTrigger")) {
|
if (params.containsKey("AddTrigger")) {
|
||||||
final String[] sVars = params.get("AddTrigger").split(" & ");
|
final String[] sVars = params.get("AddTrigger").split(" & ");
|
||||||
for (int i = 0; i < sVars.length; i++) {
|
for (int i = 0; i < sVars.length; i++) {
|
||||||
@@ -294,8 +325,9 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
addStatics = sVars;
|
addStatics = sVars;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (params.containsKey("GainsAbilitiesOf")) {
|
if (layer == StaticAbilityLayer.ABILITIES1 && params.containsKey("GainsAbilitiesOf")) {
|
||||||
final String[] valids = params.get("GainsAbilitiesOf").split(",");
|
final String[] valids = params.get("GainsAbilitiesOf").split(",");
|
||||||
ArrayList<ZoneType> validZones = new ArrayList<ZoneType>();
|
ArrayList<ZoneType> validZones = new ArrayList<ZoneType>();
|
||||||
validZones.add(ZoneType.Battlefield);
|
validZones.add(ZoneType.Battlefield);
|
||||||
@@ -326,6 +358,8 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layer == StaticAbilityLayer.RULES) {
|
||||||
|
// These fall under Rule changes, as they don't fit any other category
|
||||||
if (params.containsKey("MayLookAt")) {
|
if (params.containsKey("MayLookAt")) {
|
||||||
controllerMayLookAt = true;
|
controllerMayLookAt = true;
|
||||||
}
|
}
|
||||||
@@ -342,6 +376,7 @@ public class StaticAbilityContinuous {
|
|||||||
String cost = params.get("IgnoreEffectCost");
|
String cost = params.get("IgnoreEffectCost");
|
||||||
buildIgnorEffectAbility(stAb, cost, affectedPlayers, affectedCards);
|
buildIgnorEffectAbility(stAb, cost, affectedPlayers, affectedCards);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// modify players
|
// modify players
|
||||||
for (final Player p : affectedPlayers) {
|
for (final Player p : affectedPlayers) {
|
||||||
@@ -353,6 +388,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layer == StaticAbilityLayer.RULES) {
|
||||||
if (params.containsKey("SetMaxHandSize")) {
|
if (params.containsKey("SetMaxHandSize")) {
|
||||||
String mhs = params.get("SetMaxHandSize");
|
String mhs = params.get("SetMaxHandSize");
|
||||||
if (mhs.equals("Unlimited")) {
|
if (mhs.equals("Unlimited")) {
|
||||||
@@ -373,13 +409,14 @@ public class StaticAbilityContinuous {
|
|||||||
AbilityUtils.applyManaColorConversion(p, params);
|
AbilityUtils.applyManaColorConversion(p, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// start modifying the cards
|
// start modifying the cards
|
||||||
for (int i = 0; i < affectedCards.size(); i++) {
|
for (int i = 0; i < affectedCards.size(); i++) {
|
||||||
final Card affectedCard = affectedCards.get(i);
|
final Card affectedCard = affectedCards.get(i);
|
||||||
|
|
||||||
// Gain control
|
// Gain control
|
||||||
if (params.containsKey("GainControl")) {
|
if (layer == StaticAbilityLayer.CONTROL && params.containsKey("GainControl")) {
|
||||||
affectedCard.addTempController(hostCard.getController(), hostCard.getTimestamp());
|
affectedCard.addTempController(hostCard.getController(), hostCard.getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +440,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set P/T
|
// set P/T
|
||||||
|
if (layer == StaticAbilityLayer.SETPT) {
|
||||||
if (params.containsKey("CharacteristicDefining")) {
|
if (params.containsKey("CharacteristicDefining")) {
|
||||||
if (setPower != -1) {
|
if (setPower != -1) {
|
||||||
affectedCard.setBasePower(setPower);
|
affectedCard.setBasePower(setPower);
|
||||||
@@ -410,8 +448,8 @@ public class StaticAbilityContinuous {
|
|||||||
if (setToughness != -1) {
|
if (setToughness != -1) {
|
||||||
affectedCard.setBaseToughness(setToughness);
|
affectedCard.setBaseToughness(setToughness);
|
||||||
}
|
}
|
||||||
} else // non CharacteristicDefining
|
} else if ((setPower != -1) || (setToughness != -1)) {
|
||||||
if ((setPower != -1) || (setToughness != -1)) {
|
// non CharacteristicDefining
|
||||||
if (setP.startsWith("AffectedX")) {
|
if (setP.startsWith("AffectedX")) {
|
||||||
setPower = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, setP));
|
setPower = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, setP));
|
||||||
}
|
}
|
||||||
@@ -420,8 +458,10 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
affectedCard.addNewPT(setPower, setToughness, hostCard.getTimestamp());
|
affectedCard.addNewPT(setPower, setToughness, hostCard.getTimestamp());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add P/T bonus
|
// add P/T bonus
|
||||||
|
if (layer == StaticAbilityLayer.MODIFYPT) {
|
||||||
if (addP.startsWith("AffectedX")) {
|
if (addP.startsWith("AffectedX")) {
|
||||||
powerBonus = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, addP));
|
powerBonus = CardFactoryUtil.xCount(affectedCard, AbilityUtils.getSVar(stAb, addP));
|
||||||
se.addXMapValue(affectedCard, powerBonus);
|
se.addXMapValue(affectedCard, powerBonus);
|
||||||
@@ -432,6 +472,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
affectedCard.addSemiPermanentPowerBoost(powerBonus);
|
affectedCard.addSemiPermanentPowerBoost(powerBonus);
|
||||||
affectedCard.addSemiPermanentToughnessBoost(toughnessBonus);
|
affectedCard.addSemiPermanentToughnessBoost(toughnessBonus);
|
||||||
|
}
|
||||||
|
|
||||||
// add keywords
|
// add keywords
|
||||||
// TODO regular keywords currently don't try to use keyword multiplier
|
// TODO regular keywords currently don't try to use keyword multiplier
|
||||||
@@ -517,8 +558,7 @@ public class StaticAbilityContinuous {
|
|||||||
|
|
||||||
// add colors
|
// add colors
|
||||||
if (addColors != null) {
|
if (addColors != null) {
|
||||||
final long t = affectedCard.addColor(addColors, !se.isOverwriteColors(), true);
|
affectedCard.addColor(addColors, !se.isOverwriteColors(), hostCard.getTimestamp());
|
||||||
se.addTimestamp(affectedCard, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add triggers
|
// add triggers
|
||||||
@@ -545,7 +585,7 @@ public class StaticAbilityContinuous {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove triggers
|
// remove triggers
|
||||||
if (params.containsKey("RemoveTriggers") || removeAllAbilities) {
|
if (layer == StaticAbilityLayer.ABILITIES2 && (params.containsKey("RemoveTriggers") || removeAllAbilities)) {
|
||||||
for (final Trigger trigger : affectedCard.getTriggers()) {
|
for (final Trigger trigger : affectedCard.getTriggers()) {
|
||||||
trigger.setTemporarilySuppressed(true);
|
trigger.setTemporarilySuppressed(true);
|
||||||
}
|
}
|
||||||
@@ -575,7 +615,7 @@ public class StaticAbilityContinuous {
|
|||||||
return affectedCards;
|
return affectedCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void buildIgnorEffectAbility(final StaticAbility stAb, final String costString, final List<Player> players, final List<Card> cards) {
|
private static void buildIgnorEffectAbility(final StaticAbility stAb, final String costString, final List<Player> players, final CardCollectionView cards) {
|
||||||
final List<Player> validActivator = new ArrayList<Player>(players);
|
final List<Player> validActivator = new ArrayList<Player>(players);
|
||||||
for (final Card c : cards) {
|
for (final Card c : cards) {
|
||||||
validActivator.add(c.getController());
|
validActivator.add(c.getController());
|
||||||
@@ -637,19 +677,18 @@ public class StaticAbilityContinuous {
|
|||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Card> getAffectedCards(final StaticAbility stAb) {
|
private static CardCollectionView getAffectedCards(final StaticAbility stAb) {
|
||||||
final Map<String, String> params = stAb.getMapParams();
|
final Map<String, String> params = stAb.getMapParams();
|
||||||
final Card hostCard = stAb.getHostCard();
|
final Card hostCard = stAb.getHostCard();
|
||||||
final Game game = hostCard.getGame();
|
final Game game = hostCard.getGame();
|
||||||
final Player controller = hostCard.getController();
|
final Player controller = hostCard.getController();
|
||||||
|
|
||||||
if (params.containsKey("CharacteristicDefining")) {
|
if (params.containsKey("CharacteristicDefining")) {
|
||||||
return Lists.newArrayList(hostCard); // will always be the card itself
|
return new CardCollection(hostCard); // will always be the card itself
|
||||||
}
|
}
|
||||||
|
|
||||||
// non - CharacteristicDefining
|
// non - CharacteristicDefining
|
||||||
CardCollection affectedCards;
|
CardCollection affectedCards;
|
||||||
|
|
||||||
if (params.containsKey("AffectedZone")) {
|
if (params.containsKey("AffectedZone")) {
|
||||||
affectedCards = new CardCollection(game.getCardsIn(ZoneType.listValueOf(params.get("AffectedZone"))));
|
affectedCards = new CardCollection(game.getCardsIn(ZoneType.listValueOf(params.get("AffectedZone"))));
|
||||||
} else {
|
} else {
|
||||||
@@ -672,7 +711,7 @@ public class StaticAbilityContinuous {
|
|||||||
if (params.containsKey("Affected")) {
|
if (params.containsKey("Affected")) {
|
||||||
affectedCards = CardLists.getValidCards(affectedCards, params.get("Affected").split(","), controller, hostCard);
|
affectedCards = CardLists.getValidCards(affectedCards, params.get("Affected").split(","), controller, hostCard);
|
||||||
}
|
}
|
||||||
affectedCards.removeAll((List<?>)stAb.getIgnoreEffectCards());
|
affectedCards.removeAll((List<?>) stAb.getIgnoreEffectCards());
|
||||||
return affectedCards;
|
return affectedCards;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package forge.game.staticability;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
public enum StaticAbilityLayer {
|
||||||
|
|
||||||
|
/** Layer 2 for control-changing effects. */
|
||||||
|
CONTROL,
|
||||||
|
|
||||||
|
/** Layer 3 for text-changing effects. */
|
||||||
|
TEXT,
|
||||||
|
|
||||||
|
/** Layer 4 for type-changing effects. */
|
||||||
|
TYPE,
|
||||||
|
|
||||||
|
/** Layer 5 for color-changing effects. */
|
||||||
|
COLOR,
|
||||||
|
|
||||||
|
/** Layer 6 for ability-removing and -copying effects. */
|
||||||
|
ABILITIES1,
|
||||||
|
|
||||||
|
/** Layer 6 for ability-granting effects. */
|
||||||
|
ABILITIES2,
|
||||||
|
|
||||||
|
/** Layer 7a for characteristic-defining power/toughness effects. */
|
||||||
|
CHARACTERISTIC,
|
||||||
|
|
||||||
|
/** Layer 7b for power- and/or toughness-setting effects. */
|
||||||
|
SETPT,
|
||||||
|
|
||||||
|
/** Layer 7c for power- and/or toughness-modifying effects. */
|
||||||
|
MODIFYPT,
|
||||||
|
|
||||||
|
/** Layer for game rule-changing effects. */
|
||||||
|
RULES;
|
||||||
|
|
||||||
|
public final static ImmutableList<StaticAbilityLayer> CONTINUOUS_LAYERS =
|
||||||
|
ImmutableList.of(CONTROL, TEXT, TYPE, COLOR, ABILITIES1, ABILITIES2, CHARACTERISTIC, SETPT, MODIFYPT, RULES);
|
||||||
|
}
|
||||||
@@ -1,50 +1,27 @@
|
|||||||
package forge.trackable;
|
package forge.trackable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import forge.game.IIdentifiable;
|
import forge.game.IIdentifiable;
|
||||||
|
|
||||||
//base class for objects that can be tracked and synced between game server and GUI
|
//base class for objects that can be tracked and synced between game server and GUI
|
||||||
public abstract class TrackableObject implements IIdentifiable {
|
public abstract class TrackableObject implements IIdentifiable {
|
||||||
private static int freezeCounter = 0;
|
|
||||||
public static void freeze() {
|
|
||||||
freezeCounter++;
|
|
||||||
}
|
|
||||||
public static void unfreeze() {
|
|
||||||
if (freezeCounter == 0 || --freezeCounter > 0 || delayedPropChanges.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//after being unfrozen, ensure all changes delayed during freeze are now applied
|
|
||||||
for (DelayedPropChange change : delayedPropChanges) {
|
|
||||||
change.object.set(change.prop, change.value);
|
|
||||||
}
|
|
||||||
delayedPropChanges.clear();
|
|
||||||
}
|
|
||||||
private static class DelayedPropChange {
|
|
||||||
private final TrackableObject object;
|
|
||||||
private final TrackableProperty prop;
|
|
||||||
private final Object value;
|
|
||||||
private DelayedPropChange(TrackableObject object0, TrackableProperty prop0, Object value0) {
|
|
||||||
object = object0;
|
|
||||||
prop = prop0;
|
|
||||||
value = value0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static final ArrayList<DelayedPropChange> delayedPropChanges = new ArrayList<DelayedPropChange>();
|
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
private final EnumMap<TrackableProperty, Object> props;
|
protected final transient Tracker tracker;
|
||||||
private final EnumSet<TrackableProperty> changedProps;
|
private final Map<TrackableProperty, Object> props;
|
||||||
|
private final Set<TrackableProperty> changedProps;
|
||||||
|
|
||||||
protected TrackableObject(int id0) {
|
protected TrackableObject(final int id0, final Tracker tracker) {
|
||||||
id = id0;
|
id = id0;
|
||||||
|
this.tracker = tracker;
|
||||||
props = new EnumMap<TrackableProperty, Object>(TrackableProperty.class);
|
props = new EnumMap<TrackableProperty, Object>(TrackableProperty.class);
|
||||||
changedProps = EnumSet.noneOf(TrackableProperty.class);
|
changedProps = EnumSet.noneOf(TrackableProperty.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public final int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,13 +31,13 @@ public abstract class TrackableObject implements IIdentifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object o) {
|
public final boolean equals(final Object o) {
|
||||||
if (o == null) { return false; }
|
if (o == null) { return false; }
|
||||||
return o.hashCode() == id && o.getClass().equals(getClass());
|
return o.hashCode() == id && o.getClass().equals(getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> T get(TrackableProperty key) {
|
protected final <T> T get(final TrackableProperty key) {
|
||||||
T value = (T)props.get(key);
|
T value = (T)props.get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = key.getDefaultValue();
|
value = key.getDefaultValue();
|
||||||
@@ -68,9 +45,9 @@ public abstract class TrackableObject implements IIdentifiable {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> void set(TrackableProperty key, T value) {
|
protected final <T> void set(final TrackableProperty key, final T value) {
|
||||||
if (freezeCounter > 0 && key.respectFreeze()) { //if trackable objects currently frozen, queue up delayed prop change
|
if (tracker != null && tracker.isFrozen() && key.respectFreeze()) { //if trackable objects currently frozen, queue up delayed prop change
|
||||||
delayedPropChanges.add(new DelayedPropChange(this, key, value));
|
tracker.addDelayedPropChange(this, key, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null || value.equals(key.getDefaultValue())) {
|
if (value == null || value.equals(key.getDefaultValue())) {
|
||||||
@@ -84,11 +61,11 @@ public abstract class TrackableObject implements IIdentifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//use when updating collection type properties with using set
|
//use when updating collection type properties with using set
|
||||||
protected void flagAsChanged(TrackableProperty key) {
|
protected final void flagAsChanged(final TrackableProperty key) {
|
||||||
changedProps.add(key);
|
changedProps.add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void serialize(TrackableSerializer ts) {
|
public final void serialize(final TrackableSerializer ts) {
|
||||||
ts.write(changedProps.size());
|
ts.write(changedProps.size());
|
||||||
for (TrackableProperty key : changedProps) {
|
for (TrackableProperty key : changedProps) {
|
||||||
ts.write(TrackableProperty.serialize(key));
|
ts.write(TrackableProperty.serialize(key));
|
||||||
@@ -97,7 +74,7 @@ public abstract class TrackableObject implements IIdentifiable {
|
|||||||
changedProps.clear();
|
changedProps.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deserialize(TrackableDeserializer td) {
|
public final void deserialize(final TrackableDeserializer td) {
|
||||||
int count = td.readInt();
|
int count = td.readInt();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
TrackableProperty key = TrackableProperty.deserialize(td.readInt());
|
TrackableProperty key = TrackableProperty.deserialize(td.readInt());
|
||||||
|
|||||||
47
forge-game/src/main/java/forge/trackable/Tracker.java
Normal file
47
forge-game/src/main/java/forge/trackable/Tracker.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package forge.trackable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
public class Tracker {
|
||||||
|
private int freezeCounter = 0;
|
||||||
|
private final List<DelayedPropChange> delayedPropChanges = Lists.newArrayList();
|
||||||
|
|
||||||
|
public final boolean isFrozen() {
|
||||||
|
return freezeCounter > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void freeze() {
|
||||||
|
freezeCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unfreeze() {
|
||||||
|
if (!isFrozen() || --freezeCounter > 0 || delayedPropChanges.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//after being unfrozen, ensure all changes delayed during freeze are now applied
|
||||||
|
for (final DelayedPropChange change : delayedPropChanges) {
|
||||||
|
change.object.set(change.prop, change.value);
|
||||||
|
}
|
||||||
|
delayedPropChanges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDelayedPropChange(final TrackableObject object, final TrackableProperty prop, final Object value) {
|
||||||
|
delayedPropChanges.add(new DelayedPropChange(object, prop, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DelayedPropChange {
|
||||||
|
private final TrackableObject object;
|
||||||
|
private final TrackableProperty prop;
|
||||||
|
private final Object value;
|
||||||
|
private DelayedPropChange(final TrackableObject object0, final TrackableProperty prop0, final Object value0) {
|
||||||
|
object = object0;
|
||||||
|
prop = prop0;
|
||||||
|
value = value0;
|
||||||
|
}
|
||||||
|
@Override public String toString() {
|
||||||
|
return "Set " + prop + " of " + object + " to " + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -204,14 +204,17 @@ public class GuiChoose {
|
|||||||
@Override
|
@Override
|
||||||
public void valueChanged(final ListSelectionEvent ev) {
|
public void valueChanged(final ListSelectionEvent ev) {
|
||||||
final T sel = list.getSelectedValue();
|
final T sel = list.getSelectedValue();
|
||||||
|
if (sel instanceof InventoryItem) {
|
||||||
|
CMatchUI.SINGLETON_INSTANCE.setCard((InventoryItem) list.getSelectedValue());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final CardView card;
|
final CardView card;
|
||||||
if (sel instanceof CardStateView) {
|
if (sel instanceof CardStateView) {
|
||||||
card = ((CardStateView) sel).getCard();
|
card = ((CardStateView) sel).getCard();
|
||||||
}
|
} else if (sel instanceof CardView) {
|
||||||
else if (sel instanceof CardView) {
|
|
||||||
card = (CardView) sel;
|
card = (CardView) sel;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
card = null;
|
card = null;
|
||||||
}
|
}
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
@@ -220,9 +223,6 @@ public class GuiChoose {
|
|||||||
GuiUtils.clearPanelSelections();
|
GuiUtils.clearPanelSelections();
|
||||||
GuiUtils.setPanelSelection(card);
|
GuiUtils.setPanelSelection(card);
|
||||||
}
|
}
|
||||||
if (list.getSelectedValue() instanceof InventoryItem) {
|
|
||||||
CMatchUI.SINGLETON_INSTANCE.setCard((InventoryItem) list.getSelectedValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ public class VAssignDamage {
|
|||||||
}
|
}
|
||||||
else if (defender instanceof PlayerView) {
|
else if (defender instanceof PlayerView) {
|
||||||
final PlayerView p = (PlayerView)defender;
|
final PlayerView p = (PlayerView)defender;
|
||||||
fakeCard = new CardView(-1, defender.toString(), p, CMatchUI.SINGLETON_INSTANCE.avatarImages.get(p.getLobbyPlayerName()));
|
fakeCard = new CardView(-1, null, defender.toString(), p, CMatchUI.SINGLETON_INSTANCE.avatarImages.get(p.getLobbyPlayerName()));
|
||||||
}
|
}
|
||||||
addPanelForDefender(pnlDefenders, fakeCard);
|
addPanelForDefender(pnlDefenders, fakeCard);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ public class CardZoom extends FOverlay {
|
|||||||
}
|
}
|
||||||
if (item instanceof InventoryItem) {
|
if (item instanceof InventoryItem) {
|
||||||
InventoryItem ii = (InventoryItem)item;
|
InventoryItem ii = (InventoryItem)item;
|
||||||
return new CardView(-1, ii.getName(), null, ImageKeys.getImageKey(ii, false));
|
return new CardView(-1, null, ii.getName(), null, ImageKeys.getImageKey(ii, false));
|
||||||
}
|
}
|
||||||
return new CardView(-1, item.toString());
|
return new CardView(-1, null, item.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
final List<CardView> options = Lists.newArrayList();
|
final List<CardView> options = Lists.newArrayList();
|
||||||
for (final Entry<Player, Card> kv : ev.cards.entries()) {
|
for (final Entry<Player, Card> kv : ev.cards.entries()) {
|
||||||
//use fake card so real cards appear with proper formatting
|
//use fake card so real cards appear with proper formatting
|
||||||
final CardView fakeCard = new CardView(-1, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
|
final CardView fakeCard = new CardView(-1, null, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
|
||||||
options.add(fakeCard);
|
options.add(fakeCard);
|
||||||
options.add(kv.getValue().getView());
|
options.add(kv.getValue().getView());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1205,11 +1205,11 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
tempShowCards(pile2);
|
tempShowCards(pile2);
|
||||||
|
|
||||||
final List<CardView> cards = Lists.newArrayListWithCapacity(pile1.size() + pile2.size() + 2);
|
final List<CardView> cards = Lists.newArrayListWithCapacity(pile1.size() + pile2.size() + 2);
|
||||||
final CardView pileView1 = new CardView(Integer.MIN_VALUE, "--- Pile 1 ---");
|
final CardView pileView1 = new CardView(Integer.MIN_VALUE, null, "--- Pile 1 ---");
|
||||||
cards.add(pileView1);
|
cards.add(pileView1);
|
||||||
cards.addAll(CardView.getCollection(pile1));
|
cards.addAll(CardView.getCollection(pile1));
|
||||||
|
|
||||||
final CardView pileView2 = new CardView(Integer.MIN_VALUE + 1, "--- Pile 2 ---");
|
final CardView pileView2 = new CardView(Integer.MIN_VALUE + 1, null, "--- Pile 2 ---");
|
||||||
cards.add(pileView2);
|
cards.add(pileView2);
|
||||||
cards.addAll(CardView.getCollection(pile2));
|
cards.addAll(CardView.getCollection(pile2));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user