mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
- Move changed card colors to the Card rather than CardState
- Fix Kusari-Gama
This commit is contained in:
@@ -262,7 +262,6 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!c.isToken() && !toBattlefield) {
|
if (!c.isToken() && !toBattlefield) {
|
||||||
copied.getCurrentState().resetCardColor();
|
|
||||||
copied.clearDevoured();
|
copied.clearDevoured();
|
||||||
copied.clearDelved();
|
copied.clearDelved();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,8 +120,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private final Map<Player, CardPlayOption> mayPlay = Maps.newTreeMap();
|
private final Map<Player, CardPlayOption> mayPlay = Maps.newTreeMap();
|
||||||
|
|
||||||
// changes by AF animate and continuous static effects - timestamp is the key of maps
|
// changes by AF animate and continuous static effects - timestamp is the key of maps
|
||||||
private Map<Long, CardChangedType> changedCardTypes = new ConcurrentSkipListMap<Long, CardChangedType>();
|
private final Map<Long, CardChangedType> changedCardTypes = new ConcurrentSkipListMap<Long, CardChangedType>();
|
||||||
private Map<Long, KeywordsChange> changedCardKeywords = new ConcurrentSkipListMap<Long, KeywordsChange>();
|
private final Map<Long, KeywordsChange> changedCardKeywords = new ConcurrentSkipListMap<Long, KeywordsChange>();
|
||||||
|
private final SortedMap<Long, CardColor> changedCardColors = new ConcurrentSkipListMap<Long, CardColor>();
|
||||||
|
|
||||||
// changes that say "replace each instance of one [color,type] by another - timestamp is the key of maps
|
// changes that say "replace each instance of one [color,type] by another - timestamp is the key of maps
|
||||||
private final CardChangedWords changedTextColors = new CardChangedWords();
|
private final CardChangedWords changedTextColors = new CardChangedWords();
|
||||||
@@ -739,7 +740,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return colorsPaid;
|
return colorsPaid;
|
||||||
}
|
}
|
||||||
public final void setColorsPaid(final byte s) {
|
public final void setColorsPaid(final byte s) {
|
||||||
colorsPaid = s; // TODO: Append colors instead of replacing
|
colorsPaid |= s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getXManaCostPaid() {
|
public final int getXManaCostPaid() {
|
||||||
@@ -1080,29 +1081,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return currentState.getManaCost();
|
return currentState.getManaCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addColor(final String s, final boolean addToColors, final long timestamp) {
|
|
||||||
currentState.addColor(s, addToColors, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void removeColor(final long timestamp) {
|
|
||||||
currentState.removeColor(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setColor(final byte color) {
|
|
||||||
currentState.setColor(new CardColor(color));
|
|
||||||
}
|
|
||||||
public final void setColor(final String color) {
|
|
||||||
currentState.setColor(new CardColor(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final ColorSet determineColor() {
|
|
||||||
if (isImmutable()) {
|
|
||||||
return ColorSet.getNullColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentState.determineColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Player getChosenPlayer() {
|
public final Player getChosenPlayer() {
|
||||||
return chosenPlayer;
|
return chosenPlayer;
|
||||||
}
|
}
|
||||||
@@ -2449,6 +2427,41 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
currentState.getView().updateType(currentState);
|
currentState.getView().updateType(currentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void addColor(final String s, final boolean addToColors, final long timestamp) {
|
||||||
|
changedCardColors.put(timestamp, new CardColor(s, addToColors, timestamp));
|
||||||
|
currentState.getView().updateColors(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void removeColor(final long timestampIn) {
|
||||||
|
final CardColor removeCol = changedCardColors.remove(timestampIn);
|
||||||
|
|
||||||
|
if (removeCol != null) {
|
||||||
|
currentState.getView().updateColors(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setColor(final String color) {
|
||||||
|
currentState.setColor(color);
|
||||||
|
currentState.getView().updateColors(this);
|
||||||
|
}
|
||||||
|
public final void setColor(final byte color) {
|
||||||
|
currentState.setColor(color);
|
||||||
|
currentState.getView().updateColors(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ColorSet determineColor() {
|
||||||
|
final Iterable<CardColor> colorList = changedCardColors.values();
|
||||||
|
byte colors = currentState.getColor();
|
||||||
|
for (final CardColor cc : colorList) {
|
||||||
|
if (cc.isAdditional()) {
|
||||||
|
colors |= cc.getColorMask();
|
||||||
|
} else {
|
||||||
|
colors = cc.getColorMask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ColorSet.fromMask(colors);
|
||||||
|
}
|
||||||
|
|
||||||
// values that are printed on card
|
// values that are printed on card
|
||||||
public final int getBaseLoyalty() {
|
public final int getBaseLoyalty() {
|
||||||
return baseLoyalty;
|
return baseLoyalty;
|
||||||
@@ -3687,6 +3700,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
if (!getOwner().isValid(valid, sourceController, source)) {
|
if (!getOwner().isValid(valid, sourceController, source)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (property.startsWith("ControlledBy")) {
|
||||||
|
final String valid = property.substring(13);
|
||||||
|
if (!getController().isValid(valid, sourceController, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (property.startsWith("OwnerDoesntControl")) {
|
} else if (property.startsWith("OwnerDoesntControl")) {
|
||||||
if (getOwner().equals(getController())) {
|
if (getOwner().equals(getController())) {
|
||||||
return false;
|
return false;
|
||||||
@@ -5588,6 +5606,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
runParams.put("DamageTarget", this);
|
runParams.put("DamageTarget", this);
|
||||||
runParams.put("DamageAmount", damageToAdd);
|
runParams.put("DamageAmount", damageToAdd);
|
||||||
runParams.put("IsCombatDamage", isCombat);
|
runParams.put("IsCombatDamage", isCombat);
|
||||||
|
// Defending player at the time the damage was dealt
|
||||||
|
runParams.put("DefendingPlayer", game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null);
|
||||||
getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false);
|
getGame().getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false);
|
||||||
|
|
||||||
GameEventCardDamaged.DamageType damageType = DamageType.Normal;
|
GameEventCardDamaged.DamageType damageType = DamageType.Normal;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.card;
|
package forge.game.card;
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.mana.ManaCostParser;
|
import forge.card.mana.ManaCostParser;
|
||||||
|
|
||||||
@@ -45,23 +44,10 @@ public class CardColor {
|
|||||||
return this.timestamp;
|
return this.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
CardColor(final String colors) {
|
|
||||||
this(colors, false, 0L);
|
|
||||||
}
|
|
||||||
CardColor(final String colors, final boolean addToColors, final long timestamp) {
|
CardColor(final String colors, final boolean addToColors, final long timestamp) {
|
||||||
final ManaCost mc = new ManaCost(new ManaCostParser(colors));
|
final ManaCost mc = new ManaCost(new ManaCostParser(colors));
|
||||||
this.colorMask = mc.getColorProfile();
|
this.colorMask = mc.getColorProfile();
|
||||||
this.additional = addToColors;
|
this.additional = addToColors;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
CardColor(final byte mask) {
|
|
||||||
this.colorMask = mask;
|
|
||||||
this.additional = false;
|
|
||||||
this.timestamp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final ColorSet toColorSet() {
|
|
||||||
return ColorSet.fromMask(colorMask);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,21 +20,19 @@ package forge.game.card;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.Maps;
|
|
||||||
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.card.CardTypeView;
|
import forge.card.CardTypeView;
|
||||||
import forge.card.ColorSet;
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
|
import forge.card.mana.ManaCostParser;
|
||||||
import forge.game.card.CardView.CardStateView;
|
import forge.game.card.CardView.CardStateView;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -47,7 +45,7 @@ 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 final SortedMap<Long, CardColor> cardColor = Maps.newTreeMap();
|
private byte color = MagicColor.COLORLESS;
|
||||||
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>();
|
||||||
@@ -118,52 +116,17 @@ public class CardState {
|
|||||||
view.updateManaCost(this);
|
view.updateManaCost(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void addColor(final CardColor color) {
|
public final byte getColor() {
|
||||||
cardColor.put(color.getTimestamp(), color);
|
return color;
|
||||||
getView().updateColors(this);
|
|
||||||
}
|
}
|
||||||
|
public final void setColor(final String color) {
|
||||||
public final void addColor(final String s, final boolean addToColors, final long timestamp) {
|
final ManaCostParser parser = new ManaCostParser(color);
|
||||||
addColor(new CardColor(s, addToColors, timestamp));
|
final ManaCost cost = new ManaCost(parser);
|
||||||
|
setColor(cost.getColorProfile());
|
||||||
}
|
}
|
||||||
|
public final void setColor(final byte color) {
|
||||||
public final void removeColor(final long timestampIn) {
|
this.color = color;
|
||||||
final CardColor removeCol = cardColor.remove(timestampIn);
|
view.updateColors(card);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
public final void resetCardColor() {
|
|
||||||
if (cardColor.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final Long firstKey = cardColor.firstKey();
|
|
||||||
final CardColor first = cardColor.get(firstKey);
|
|
||||||
cardColor.clear();
|
|
||||||
cardColor.put(firstKey, first);
|
|
||||||
view.updateColors(this);
|
|
||||||
}
|
|
||||||
public final ColorSet determineColor() {
|
|
||||||
final Iterable<CardColor> colorList = cardColor.values();
|
|
||||||
byte colors = 0;
|
|
||||||
for (final CardColor cc : colorList) {
|
|
||||||
if (cc.isAdditional()) {
|
|
||||||
colors |= cc.getColorMask();
|
|
||||||
} else {
|
|
||||||
colors = cc.getColorMask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ColorSet.fromMask(colors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getBasePower() {
|
public final int getBasePower() {
|
||||||
@@ -389,7 +352,7 @@ public class CardState {
|
|||||||
setName(source.getName());
|
setName(source.getName());
|
||||||
setType(source.type);
|
setType(source.type);
|
||||||
setManaCost(source.getManaCost());
|
setManaCost(source.getManaCost());
|
||||||
setColor(source.cardColor);
|
setColor(source.getColor());
|
||||||
setBasePower(source.getBasePower());
|
setBasePower(source.getBasePower());
|
||||||
setBaseToughness(source.getBaseToughness());
|
setBaseToughness(source.getBaseToughness());
|
||||||
intrinsicKeywords = new ArrayList<String>(source.intrinsicKeywords);
|
intrinsicKeywords = new ArrayList<String>(source.intrinsicKeywords);
|
||||||
|
|||||||
@@ -770,7 +770,7 @@ public class CardView extends GameEntityView {
|
|||||||
set(TrackableProperty.Colors, c.determineColor());
|
set(TrackableProperty.Colors, c.determineColor());
|
||||||
}
|
}
|
||||||
void updateColors(CardState c) {
|
void updateColors(CardState c) {
|
||||||
set(TrackableProperty.Colors, c.determineColor());
|
set(TrackableProperty.Colors, c.getColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getImageKey(PlayerView viewer) {
|
public String getImageKey(PlayerView viewer) {
|
||||||
|
|||||||
@@ -532,6 +532,8 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
runParams.put("DamageTarget", this);
|
runParams.put("DamageTarget", this);
|
||||||
runParams.put("DamageAmount", amount);
|
runParams.put("DamageAmount", amount);
|
||||||
runParams.put("IsCombatDamage", isCombat);
|
runParams.put("IsCombatDamage", isCombat);
|
||||||
|
// Defending player at the time the damage was dealt
|
||||||
|
runParams.put("DefendingPlayer", game.getCombat() != null ? game.getCombat().getDefendingPlayerRelatedTo(source) : null);
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false);
|
game.getTriggerHandler().runTrigger(TriggerType.DamageDone, runParams, false);
|
||||||
|
|
||||||
game.fireEvent(new GameEventPlayerDamaged(this, source, amount, isCombat, infect));
|
game.fireEvent(new GameEventPlayerDamaged(this, source, amount, isCombat, infect));
|
||||||
|
|||||||
@@ -104,5 +104,7 @@ public class TriggerDamageDone extends Trigger {
|
|||||||
sa.setTriggeringObject("Source", this.getRunParams().get("DamageSource"));
|
sa.setTriggeringObject("Source", this.getRunParams().get("DamageSource"));
|
||||||
sa.setTriggeringObject("Target", this.getRunParams().get("DamageTarget"));
|
sa.setTriggeringObject("Target", this.getRunParams().get("DamageTarget"));
|
||||||
sa.setTriggeringObject("DamageAmount", this.getRunParams().get("DamageAmount"));
|
sa.setTriggeringObject("DamageAmount", this.getRunParams().get("DamageAmount"));
|
||||||
|
// This parameter is here because LKI information related to combat doesn't work properly
|
||||||
|
sa.setTriggeringObject("DefendingPlayer", this.getRunParams().get("DefendingPlayer"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ K:Equip 3
|
|||||||
S:Mode$ Continuous | Affected$ Card.EquippedBy | AddAbility$ GamaPump | Description$ Equipped creature has "{2}: This creature gets +1/+0 until end of turn."
|
S:Mode$ Continuous | Affected$ Card.EquippedBy | AddAbility$ GamaPump | Description$ Equipped creature has "{2}: This creature gets +1/+0 until end of turn."
|
||||||
SVar:GamaPump:AB$ Pump | Cost$ 2 | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
|
SVar:GamaPump:AB$ Pump | Cost$ 2 | NumAtt$ +1 | SpellDescription$ CARDNAME gets +1/+0 until end of turn.
|
||||||
T:Mode$ DamageDone | ValidSource$ Card.EquippedBy | ValidTarget$ Creature.blocking | Execute$ KusariPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever equipped creature deals damage to a blocking creature, CARDNAME deals that much damage to each other creature defending player controls.
|
T:Mode$ DamageDone | ValidSource$ Card.EquippedBy | ValidTarget$ Creature.blocking | Execute$ KusariPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever equipped creature deals damage to a blocking creature, CARDNAME deals that much damage to each other creature defending player controls.
|
||||||
SVar:KusariPump:DB$ Pump | Defined$ TriggeredTarget | RememberObjects$ TriggeredTarget | SubAbility$ GamaDamage
|
SVar:KusariPump:DB$ Pump | Defined$ Self | RememberObjects$ TriggeredTarget | SubAbility$ KusariPump2
|
||||||
SVar:GamaDamage:DB$ DamageAll | NumDmg$ X | References$ X | ValidCards$ Creature.DefenderCtrl+IsNotRemembered | SubAbility$ CleanUp
|
SVar:KusariPump2:DB$ Pump | Defined$ Self | RememberObjects$ TriggeredDefendingPlayer | SubAbility$ GamaDamage
|
||||||
|
SVar:GamaDamage:DB$ DamageAll | NumDmg$ X | References$ X | ValidCards$ Creature.IsNotRemembered+ControlledBy Player.IsRemembered | SubAbility$ CleanUp
|
||||||
SVar:CleanUp:DB$ Cleanup | ClearRemembered$ True
|
SVar:CleanUp:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:X:TriggerCount$DamageAmount
|
SVar:X:TriggerCount$DamageAmount
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/kusari_gama.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/kusari_gama.jpg
|
||||||
Oracle:Equipped creature has "{2}: This creature gets +1/+0 until end of turn."\nWhenever equipped creature deals damage to a blocking creature, Kusari-Gama deals that much damage to each other creature defending player controls.\nEquip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.)
|
Oracle:Equipped creature has "{2}: This creature gets +1/+0 until end of turn."\nWhenever equipped creature deals damage to a blocking creature, Kusari-Gama deals that much damage to each other creature defending player controls.\nEquip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.)
|
||||||
Reference in New Issue
Block a user